Opened 7 years ago

Closed 7 years ago

Last modified 7 years ago

#10095 closed (duplicate)

__import__ behaviour causing signal receivers to be connected twice

Reported by: ben Owned by: nobody
Component: Core (Other) Version: master
Severity: Keywords: signal import
Cc: Triage Stage: Unreviewed
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: UI/UX:

Description

When connecting a signal we had an issue where it was getting connected twice.

The signal receivers were both defined and connected in the project's __init__.py

I've tracked this down to the use of __import__('somemod', {}, {}, ['']) specifically in core.management.setup_environ (line 251 in my checkout of django which is at rev 7305): this line:

    project_module = __import__(project_name, {}, {}, [''])

An import like this with an empty string in the fromlist arg causes my project to be imported - and therefore evaluated - twice. The second time it's imported it's added to sys.modules with the key being '<module_name>.' and the ids of the signal functions are different. This screws up the signal connection which is keyed off the id resulting in the function being connected twice.

This is probably only going to be a problem for people connecting signals in the root of their project (I count 27 time in my version of the django source where this idiom is used). However I do wonder whether it's worth making the django.dispatch.dispatcher.connect function more robust with this in mind. (I guess this might have already been done in the signal refactor?)

See http://bugs.python.org/issue2090 and http://bugs.python.org/issue4438

Change History (3)

comment:1 Changed 7 years ago by ramiro

  • Needs documentation unset
  • Needs tests unset
  • Patch needs improvement unset
  • Resolution set to duplicate
  • Status changed from new to closed

duplicate of #8193

comment:2 Changed 7 years ago by mtredinnick

Note, also, that we don't guarantee things will only be imported once. Python's __import__ statement is the same as reload(), it reimports the module, even if it already exists. It's up to code authors to make any allowances for double execution of code lines.

comment:3 Changed 7 years ago by ben

I did search first, honest I did!!!

Note: See TracTickets for help on using tickets.
Back to Top