Leonardo.Z
Leonardo.Z

Reputation: 9791

How does django manage.py put a project package on sys.path

I read the django doc and some SO posts to know the differences between manage.py and django-admin.py.

They all say:

manage.py is automatically created in each Django project. manage.py is a thin wrapper around django-admin.py that takes care of two things for you before delegating to django-admin.py:

  1. It puts your project’s package on sys.path.
  2. It sets the DJANGO_SETTINGS_MODULE environment variable so that it points to your project’s settings.py file.

So I checked the scource code of these 2 files(latest version, so it the doc).

Then I am confused. manage.py does the second thing: sets the DJANGO_SETTINGS_MODULE environment variable. Besides that, I really can not find any differences between these 2 scripts.

[django-admin.py]

#!/usr/bin/env python
from django.core import management

if __name__ == "__main__":
    management.execute_from_command_line()

[manage.py]

#!/usr/bin/env python
import os
import sys

if __name__ == "__main__":
    os.environ.setdefault("DJANGO_SETTINGS_MODULE", "{{ project_name }}.settings")

    from django.core.management import execute_from_command_line

    execute_from_command_line(sys.argv)

Why? Is the django documentation out of date? Or I missed something here? And where is the code that puts the project’s package on sys.path?

Upvotes: 5

Views: 2415

Answers (2)

x-yuri
x-yuri

Reputation: 18883

From what I can see it's not ./manage.py who "puts your project’s package on sys.path."

The doc says:

sys.path is initialized from these locations:

  • The directory containing the input script (or the current directory when no file is specified).
  • PYTHONPATH (a list of directory names, with the same syntax as the shell variable PATH).
  • The installation-dependent default.

The installation-dependent default must be what site.py adds. But it can be disabled with -S switch. Now then when I run this script (1.py):

import sys
print(sys.path)

I get:

$ python -S ../1.py   # to show that it's not current directory that is added
['/path/to/the/script/directory', '/usr/lib/python35.zip', '/usr/lib/python3.5/', \
'/usr/lib/python3.5/plat-linux', '/usr/lib/python3.5/lib-dynload']

So, when you run django-admin, /path/to/env/bin/django-admin will be the first on the sys.path. And when ./manage.py, /path/to/project.

As such, one can probably say that ./manage.py "puts your project’s package on sys.path," but indirectly, by being at the root of your project.

Upvotes: 1

Maciej Gol
Maciej Gol

Reputation: 15854

The sys.path is updated here using handle_default_options(options) statement located here. The execution path is as follows:

  • execute_from_command_line(argv) (your manage.py)
  • utility.execute() here
  • handle_default_options(options) here

The same method is used by Command class used as base class for management commands.

Upvotes: 3

Related Questions