开发者

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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜