http://code.djangoproject.com/ticket/3951
Handlers are registered twice because django fiddles with imports and
there are multiple instances of some modules which result in multiple
registrations of handlers from different modules.
The ticket is quite stagnant... and signals doesn't seem very useful
in the current state. Is anyone actually using signals?
2008/7/28 bayo opadeyi <bayok...@googlemail.com>:
>
>
> On 7/28/08, bayo opadeyi <bayok...@googlemail.com> wrote:
>>
>> I had the same problem and decided to override save() instead.
>> I thought i posted on django-users, but seems i didn't
>
>
> Whta is the implication of 'How you import your modules' with respect to
> post_save() being triggered twice?
Why yes, people are using them. And they're actually quite useful so
long as you're aware of how Python works; if this were some sort of
problem which constantly plagued the use of signals, you'd see
breakage all over the place in Django's own codebase, because Django
itself uses signals quite heavily.
--
"Bureaucrat Conrad, you are technically correct -- the best kind of correct."
I've found an ugly workaround: putting the signal registration code
into admin.py ensures it is executed only once. (But it is only a
workaround since it ties the signal registration to the use of the
admin interface). I was previously putting the signal registration
code in app/models/__init__.py (which triggers the double
registration)
I do signal-registration stuff in model files all the time, and I've
never once run into this sort of problem.
At the bottom is my solution:
http://www.djangosnippets.org/snippets/16/
The solution is to set a variable into a module that is
never used in a relative import (here 'logging', but 'sys' should work too)
|{{{
import logging
if not hasattr(logging, "set_up_done"):
logging.set_up_done=False
def set_up(myhome):
if logging.set_up_done:
return
logging.set_up_done=True
|
}}}
I know two places where a double import can occur:
- application directory is under the project dir, and you
don't use the same import path in all places
- settings.py is imported twice. The default manage.py imports
it from the same directory. I changed the automatically
created manage.py.
HTH,
Thomas Güttler
--
Thomas Guettler, http://www.thomas-guettler.de/
E-Mail: guettli (*) thomas-guettler + de
If you still have that test handy, try this in your callback function:
print your_function_name.__module__
That is the key to sys.modules; I suspect you have it twice. This is
generally caused by having overlapping directory hierarchies in
sys.path.
I'd be a proponent of Django issuing a warning any time it's started
with overlapping sys.path's.
Thoughts?
Um... yuk. :-(
It's very, very hard to avoid this happening since there's a lot of
__import__ calls in Django and you'd quite possibly be inadvertently
forcing particular directory structures on people. We have people who
struggle to bother to learn Python at the basic level before starting
with Django; requiring them to understand the mechanics of import paths
and how things are stored in sys.modules is a little rough. I personally
kind of liked leaving those constraints (on what my directory hierarchy
could look like) behind back in the mid-90's when I moved away from
having to develop for Windows.
Please try hard to come up with some other way of having uniqueness. I'd
certainly not being against just allowing a (possibly optional) UID in
the registration call to act as a key. It's easy enough to generate a
string that is almost certainly unique when I'm about call
signal.register() (fall face down on the keyboard, for example, or make
something out of the app name, class name and signal name) and it
doesn't force me not to use Python's natural ability to import things
from different places.
Still, I know this is your particular project and I'm not at all envious
of the amount of work you have to do to get it work. So maybe it's not
possible, but it would be nice if it was (<subliminal>UID</subliminal>).
Regards,
Malcolm
Maybe you put 'myapp' (without leading 'mysite.') on urls.py,
INSTALLED_APPS, or other declarative setting?
--
Leo Soto M.
http://blog.leosoto.com
Ah, but having stuff, in general, loaded twice is not good. The fact
that it shows up in the ORM and the signal handlers is an annoying
symptom of a larger problem, no?
I meant that by issuing a warning, it might serve as a flag: "you're
doing something a bit dangerous here, but you probably know what
you're doing. if you see weird problems like x or y, check your
work."
I don't think so. You have to write your code with the awareness that it
can be imported more than once, but that's not a bad habit to get into,
since it avoids trying to do once-and-only-once style initialisation and
other pieces of non-transient state management inside a module. The
simple fact of life is that it's almost impossible to avoid as a
guaranteed condition, particularly with something like Django that uses
__import__.
Malcolm
But doesn't even things like `isinstance()` break if you import the
same code from different packages and pass around the instances?
I don't really have an argument here, just a gut feeling that
importing the same thing from two locations on the same Python VM is a
bad thing. I agree that code shouldn't make assumptions about how it
is imported, thought.