why is __init__ module in django project loaded twice
I put
print 'Hello world!'
into __init__.py
in my django project. When I run ./manage.py runserver
now, I get
gruszczy@gruszczy-laptop:~/Programy/project$ ./manage.py runserver
Hello world!
Hello world!
Val开发者_如何转开发idating models...
0 errors found
Why is __init__.py
run twice? It should be loaded only once.
It should be loaded only once... per process. I'm guessing that manage.py
forks, and that two separate processes are launched. Could you print the result of os.getpid()
?
After learning the --noreload option from the above answer, I found that both
% django-admin help runserver
% manage.py help runserver
map to the below code in django/core/management/commands/runserver.py
parser.add_argument(
'--noreload', action='store_false', dest='use_reloader',
help='Tells Django to NOT use the auto-reloader.',
)
Both django-admin.py and manage.py call
django.core.management.execute_from_command_line(sys.argv)
I then started to trace the Django code to better understand why the two PIDs when --noreload is not given.
In below, we have
class BaseCommand defined in management/base.py and
class Command(BaseCommand) defined in management/commands/runserver.py
execute_from_command_line(sys.argv) ==>> utility.execute() ==>>
self.fetch_command(subcommand).run_from_argv(self.argv) ==>>
self.execute(*args, **cmd_options) in management/base.py ==>>
super().execute(*args, **options) in commands/runserver.py ==>>
output = self.handle(*args, **options) in base.py ==>>
self.run(**options) in commands/runserver.py ==>>
if use_reloader:
autoreload.run_with_reloader(self.inner_run, **options)
else:
self.inner_run(None, **options) // --noreload
ParentPID run_with_reloader() ==>> DJANGO_AUTORELOAD_ENV = None ==>>
restart_with_reloader() only runs the 1st time by PPID ==>>
==>> subprocess.call(DJANGO_AUTORELOAD_ENV = true) ==>> child process cPID
cPID run_with_reloader() ==>> "Watching for file changes with StatReloader"
==>> start_django(StatReloader, Command.inner_run) ==>>
django_main_thread = threading.Thread(target=inner_run) and
StatReloader.run(django_main_thread)
==>> Performing system checks... Starting development server at
http://127.0.0.1:8080/
The StatReloader(BaseReloader) will check file changes once per second.
If there is a a file write => notify_file_changed(timestamp delta) =>
trigger_reload() and PPID will spawn a new cPID and the old cPID is gone
so that we don't have to restart the runserver whenever there is a code change.
With the --noreload option, PPID executes inner_run() directly and skips the cPID subprocess for auto-reloading. If you kill either PPID or cPID, the whole process dies.
One simple way of finding out would be to raise an exception. Perhaps something like this in your init.py:
import os
if os.path.isfile('/tmp/once.log'):
raise Exception
open('/tmp/once.log','w').write('first time')
Then you can inspect the traceback.
精彩评论