why is __init__ module in django project loaded twice

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.

Tags:

Python

Django