if __name__ =='__main__':
os.environ.setdefault('DJANGO_SETTINGS_MODULE','mysite.settings')try:from django.core.management import execute_from_command_line
except ImportError as exc:raise ImportError("Couldn't import Django. Are you sure it's installed and ""available on your PYTHONPATH environment variable? Did you ""forget to activate a virtual environment?")from exc
execute_from_command_line(sys.argv)
raise A from B 是一种很Pythonic的关于异常处理的写法,这篇文章讲的很清楚。设置环境变量之后,命令参数的列表传到了 execute_from_command_line 中。
命令管理工具
# django\core\management\ __init__.pydefexecute_from_command_line(argv=None):"""Run a ManagementUtility."""
utility = ManagementUtility(argv)
utility.execute()classManagementUtility:"""
Encapsulate the logic of the django-admin and manage.py utilities.
"""def__init__(self, argv=None):
self.argv = argv or sys.argv[:]
self.prog_name = os.path.basename(self.argv[0])if self.prog_name =='__main__.py':
self.prog_name ='python -m django'
self.settings_exception =None
# django\core\management\__init__.pydefexecute(self):"""
Given the command-line arguments, figure out which subcommand is being
run, create a parser appropriate to that command, and run it.
"""try:
subcommand = self.argv[1]except IndexError:
subcommand ='help'# Display help if no arguments were given.# Preprocess options to extract --settings and --pythonpath.# These options could affect the commands that are available, so they# must be processed early.# 首先parser实例化一个CommandParser类对象解析器,并且add_argument添加如下的代码块
parser = CommandParser(usage='%(prog)s subcommand [options] [args]', add_help=False, allow_abbrev=False)
parser.add_argument('--settings')
parser.add_argument('--pythonpath')
parser.add_argument('args', nargs='*')# catch-alltry:
options, args = parser.parse_known_args(self.argv[2:])
handle_default_options(options)except CommandError:pass# Ignore any option errors at this point.try:
settings.INSTALLED_APPS
except ImproperlyConfigured as exc:
self.settings_exception = exc
except ImportError as exc:
self.settings_exception = exc
if settings.configured:# Start the auto-reloading dev server even if the code is broken.# The hardcoded condition is a code smell but we can't rely on a# flag on the command class because we haven't located it yet.if subcommand =='runserver'and'--noreload'notin self.argv:try:
autoreload.check_errors(django.setup)()except Exception:# The exception will be raised later in the child process# started by the autoreloader. Pretend it didn't happen by# loading an empty list of applications.
apps.all_models = defaultdict(OrderedDict)
apps.app_configs = OrderedDict()
apps.apps_ready = apps.models_ready = apps.ready =True# Remove options not compatible with the built-in runserver# (e.g. options for the contrib.staticfiles' runserver).# Changes here require manually testing as described in# #27522.
_parser = self.fetch_command('runserver').create_parser('django','runserver')
_options, _args = _parser.parse_known_args(self.argv[2:])for _arg in _args:
self.argv.remove(_arg)# In all other cases, django.setup() is required to succeed.else:
django.setup()
self.autocomplete()if subcommand =='help':if'--commands'in args:
sys.stdout.write(self.main_help_text(commands_only=True)+'\n')elifnot options.args:
sys.stdout.write(self.main_help_text()+'\n')else:
self.fetch_command(options.args[0]).print_help(self.prog_name, options.args[0])# Special-cases: We want 'django-admin --version' and# 'django-admin --help' to work, for backwards compatibility.elif subcommand =='version'or self.argv[1:]==['--version']:
sys.stdout.write(django.get_version()+'\n')elif self.argv[1:]in(['--help'],['-h']):
sys.stdout.write(self.main_help_text()+'\n')else:
self.fetch_command(subcommand).run_from_argv(self.argv)
# django\utils\autoreload.pydefcheck_errors(fn):
@functools.wraps(fn)defwrapper(*args,**kwargs):global _exception
try:
fn(*args,**kwargs)except Exception:
_exception = sys.exc_info()
et, ev, tb = _exception
ifgetattr(ev,'filename',None)isNone:# get the filename from the last item in the stack
filename = traceback.extract_tb(tb)[-1][0]else:
filename = ev.filename
if filename notin _error_files:
_error_files.append(filename)raisereturn wrapper
deffetch_command(self, subcommand):# Get commands outside of try block to prevent swallowing exceptions
commands = get_commands()try:
app_name = commands[subcommand]except KeyError:if os.environ.get('DJANGO_SETTINGS_MODULE'):# If `subcommand` is missing due to misconfigured settings, the# following line will retrigger an ImproperlyConfigured exception# (get_commands() swallows the original one) so the user is# informed about it.
settings.INSTALLED_APPS
else:
sys.stderr.write("No Django settings specified.\n")
possible_matches = get_close_matches(subcommand, commands)
sys.stderr.write('Unknown command: %r'% subcommand)if possible_matches:
sys.stderr.write('. Did you mean %s?'% possible_matches[0])
sys.stderr.write("\nType '%s help' for usage.\n"% self.prog_name)
sys.exit(1)ifisinstance(app_name, BaseCommand):# If the command is already loaded, use it directly.
klass = app_name
else:
klass = load_command_class(app_name, subcommand)return klass
defload_command_class(app_name, name):"""
Given a command name and an application name, return the Command
class instance. Allow all errors raised by the import process
(ImportError, AttributeError) to propagate.
"""
module = import_module('%s.management.commands.%s'%(app_name, name))return module.Command()
# django\core\management\base.pydefrun_from_argv(self, argv):"""
Set up any environment changes requested (e.g., Python path
and Django settings), then run this command. If the
command raises a ``CommandError``, intercept it and print it sensibly
to stderr. If the ``--traceback`` option is present or the raised
``Exception`` is not ``CommandError``, raise it.
"""
self._called_from_command_line =True
parser = self.create_parser(argv[0], argv[1])# 返回一个Namespace的实例
options = parser.parse_args(argv[2:])# 对象转成字典
cmd_options =vars(options)# Move positional args out of options to mimic legacy optparse
args = cmd_options.pop('args',())# 设置默认参数
handle_default_options(options)try:# 异常捕获包裹的execute
self.execute(*args,**cmd_options)except Exception as e:...defexecute(self,*args,**options):"""
Try to execute this command, performing system checks if needed (as
controlled by the ``requires_system_checks`` attribute, except if
force-skipped).
"""...if self.requires_system_checks andnot options.get('skip_checks'):
self.check()if self.requires_migrations_checks:
self.check_migrations()
output = self.handle(*args,**options)...defhandle(self,*args,**options):"""
The actual logic of the command. Subclasses must implement
this method.
"""raise NotImplementedError('subclasses of BaseCommand must provide a handle() method')