app __init.py__ question

7 views
Skip to first unread message

joep

unread,
Aug 2, 2009, 7:46:23 PM8/2/09
to Django users
Hi all,

I have both a project and an app I just created (using django-admin).
I modified the __init.py__ file in the app to execute a print
statement on import. But it gets executed twice when I start the
development server.

Oddly, it doesn't happen when I set USE_I18N = False in the settings
file. I'm new to python and django, so I'm not sure what to make of
this behavior. Is is normal? My understanding of python is that I
would expect the print statement to only execute once, but perhaps I
don't understand.

Any help in understanding greatly appreciated.

chexov

unread,
Aug 3, 2009, 3:20:30 AM8/3/09
to Django users
The thing is that i18n initialization process consists of importing
modules (again) and
"translating" it to the requested language.

You can check django.utils.translation.translation() for more info.

When i18n is disabled, no need to translate anything and django.core
imports modules only once.

Please, correct me if I'm wrong.
--
apl

Karen Tracey

unread,
Aug 3, 2009, 10:00:45 AM8/3/09
to django...@googlegroups.com

It's not quite that simple.  If, instead of putting a simple print in you app's __init__.py file, you put:

import traceback
traceback.print_stack()

you will then be able to see what code is triggering the import of __init__.py.  In the case where USE_I18N is True, you will see two identical tracebacks that look like this:

  File "manage.py", line 12, in <module>
    execute_manager(settings)
  File "/usr/lib/python2.5/site-packages/django/core/management/__init__.py", line 362, in execute_manager
    utility.execute()
  File "/usr/lib/python2.5/site-packages/django/core/management/__init__.py", line 303, in execute
    self.fetch_command(subcommand).run_from_argv(self.argv)
  File "/usr/lib/python2.5/site-packages/django/core/management/base.py", line 195, in run_from_argv
    self.execute(*args, **options.__dict__)
  File "/usr/lib/python2.5/site-packages/django/core/management/base.py", line 213, in execute
    translation.activate('en-us')
  File "/usr/lib/python2.5/site-packages/django/utils/translation/__init__.py", line 73, in activate
    return real_activate(language)
  File "/usr/lib/python2.5/site-packages/django/utils/translation/__init__.py", line 43, in delayed_loader
    return g['real_%s' % caller](*args, **kwargs)
  File "/usr/lib/python2.5/site-packages/django/utils/translation/trans_real.py", line 205, in activate
    _active[currentThread()] = translation(language)
  File "/usr/lib/python2.5/site-packages/django/utils/translation/trans_real.py", line 194, in translation
    default_translation = _fetch(settings.LANGUAGE_CODE)
  File "/usr/lib/python2.5/site-packages/django/utils/translation/trans_real.py", line 180, in _fetch
    app = import_module(appname)
  File "/usr/lib/python2.5/site-packages/django/utils/importlib.py", line 35, in import_module
    __import__(name)
  File "/home/kmt/software/web/playground/ttt/__init__.py", line 2, in <module>
    traceback.print_stack()

followed by:

Validating models...
0 errors found

Django version 1.1, using settings 'playground.settings'
Development server is running at http://127.0.0.1:9999/
Quit the server with CONTROL-C.

So indeed from the stack you can see that activating a translation  (translation.activate('en-us')) is what ultimately causes the import of the app.  This only happens if USE_I18N is True because when it is False the translation routines are replaced with do-nothing functions that don't actually do anything.  So, when USE_I18N is False the translation.activate call you see in the stack trace wouldn't actually trigger your app to get loaded.

OK, so activating a translation causes your app to be loaded.  Why does it happen twice when starting the dev server?  The reason for that is the autoreload feature of the development server.  If you run the dev server with USE_I18N set to True but the --noreload flag, you will see that __init__.py is imported only once before you get the message "Validating models...".  Essentially entering the reloader loop causes a reload, so everything that has been run up to that point gets run again, including the translation activation that triggers the import of your app, if USE_I18N is True.

OK, so why don't you see the double load when USE_I18N is False and the reloader is active?  If you look at the dev server output including stack trace from __init__.py for that case:

Validating models...
  File "/usr/lib/python2.5/site-packages/django/core/management/commands/runserver.py", line 48, in inner_run
    self.validate(display_num_errors=True)
  File "/usr/lib/python2.5/site-packages/django/core/management/base.py", line 249, in validate
    num_errors = get_validation_errors(s, app)
  File "/usr/lib/python2.5/site-packages/django/core/management/validation.py", line 28, in get_validation_errors
    for (app_name, error) in get_app_errors().items():
  File "/usr/lib/python2.5/site-packages/django/db/models/loading.py", line 131, in get_app_errors
    self._populate()
  File "/usr/lib/python2.5/site-packages/django/db/models/loading.py", line 58, in _populate
    self.load_app(app_name, True)
  File "/usr/lib/python2.5/site-packages/django/db/models/loading.py", line 74, in load_app
    models = import_module('.models', app_name)
  File "/usr/lib/python2.5/site-packages/django/utils/importlib.py", line 35, in import_module
    __import__(name)
  File "/home/kmt/software/web/playground/ttt/__init__.py", line 2, in <module>
    traceback.print_stack()
0 errors found

Django version 1.1, using settings 'playground.settings'
Development server is running at http://127.0.0.1:9999/
Quit the server with CONTROL-C.

In this case your app isn't loaded until after the "Validating models..." message is printed.  This is code that runs after the reloader reloads the first time.  Disabling USE_I18N essentially moves the loading of your app from before entry to the reloader loop into the code that runs after the reloader enters the main processing loop.  In this case you will see that your app gets loaded again when you do something that forces the reloader to reload again (i.e. change a code file).

Clear as mud?

Karen

chexov

unread,
Aug 3, 2009, 11:31:45 AM8/3/09
to Django users


On Aug 3, 5:00 pm, Karen Tracey <kmtra...@gmail.com> wrote:
> Development server is running athttp://127.0.0.1:9999/
> Quit the server with CONTROL-C.
>
> So indeed from the stack you can see that activating a translation
> (translation.activate('en-us')) is what ultimately causes the import of the
> app.  This only happens if USE_I18N is True because when it is False the
> translation routines are replaced with do-nothing functions that don't
> actually do anything.  So, when USE_I18N is False the translation.activate
> call you see in the stack trace wouldn't actually trigger your app to get
> loaded.
>
> OK, so activating a translation causes your app to be loaded.  Why does it
> happen twice when starting the dev server?  The reason for that is the
> autoreload feature of the development server.  If you run the dev server
> with USE_I18N set to True but the --noreload flag, you will see that
> __init__.py is imported only once before you get the message "Validating
> models...".  Essentially entering the reloader loop causes a reload, so
> everything that has been run up to that point gets run again, including the
> translation activation that triggers the import of your app, if USE_I18N is
> True.
>
> OK, so why don't you see the double load when USE_I18N is False and the
> reloader is active?  If you look at the dev server output including stack
> trace from __init__.py for that case:
>
> Validating models...
>   File
> "/usr/lib/python2.5/site-packages/django/core/management/commands/runserver .py",
> Development server is running athttp://127.0.0.1:9999/
> Quit the server with CONTROL-C.
>
> In this case your app isn't loaded until after the "Validating models..."
> message is printed.  This is code that runs after the reloader reloads the
> first time.  Disabling USE_I18N essentially moves the loading of your app
> from before entry to the reloader loop into the code that runs after the
> reloader enters the main processing loop.  In this case you will see that
> your app gets loaded again when you do something that forces the reloader to
> reload again (i.e. change a code file).
>
> Clear as mud?

Clear. Thanks for the answer.
What cause the autoreloader to reload the modules?
Is it reacts only when source code files was changed?

>
> Karen

joep

unread,
Aug 3, 2009, 4:07:52 PM8/3/09
to Django users
Thanks Karen. That helps a lot. I have more questions about what is
going on, but I'll read through the translation section of the docs
first to see if the answers are there first.

Karen Tracey

unread,
Aug 3, 2009, 7:37:16 PM8/3/09
to django...@googlegroups.com
On Mon, Aug 3, 2009 at 11:31 AM, chexov <anton.l...@gmail.com> wrote:
Clear. Thanks for the answer.
What cause the autoreloader to reload the modules?
Is it reacts only when source code files was changed?

Yes, it reloads when it detects that a source file has changed on disk, to make development easier so you do not have to remember to restart the dev server every time you change code.  Note it doesn't just manually re-load certain modules, rather it spawns an entirely new process and starts all over from the beginning when it decides to reload.

Karen
Reply all
Reply to author
Forward
0 new messages