post_save signal triggered twice

36 views
Skip to first unread message

Alex Rades

unread,
Jul 25, 2008, 10:10:46 AM7/25/08
to django-d...@googlegroups.com
Hi,
is there a non-obvious reason for signals like post_save being
triggered twice for each save?

Alex Koshelev

unread,
Jul 25, 2008, 12:21:16 PM7/25/08
to Django developers
You register same handler twiсe. Check the way you import your
modules.

Alex Rades

unread,
Jul 28, 2008, 6:47:24 AM7/28/08
to django...@googlegroups.com, Alex Koshelev, django-d...@googlegroups.com
Hi,
the problem is described here:

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?

>>> http://www.qrapht.com

James Bennett

unread,
Jul 28, 2008, 7:24:26 AM7/28/08
to django-d...@googlegroups.com
2008/7/28 Alex Rades <aler...@gmail.com>:

> The ticket is quite stagnant... and signals doesn't seem very useful
> in the current state. Is anyone actually using signals?

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."

Alex Rades

unread,
Jul 28, 2008, 8:04:09 AM7/28/08
to django-d...@googlegroups.com
On Mon, Jul 28, 2008 at 1:24 PM, James Bennett <ubern...@gmail.com> wrote:
>
> 2008/7/28 Alex Rades <aler...@gmail.com>:
>> The ticket is quite stagnant... and signals doesn't seem very useful
>> in the current state. Is anyone actually using signals?
>
> 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.

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)

James Bennett

unread,
Jul 28, 2008, 9:14:19 AM7/28/08
to django-d...@googlegroups.com
On Mon, Jul 28, 2008 at 7:04 AM, Alex Rades <aler...@gmail.com> wrote:
> 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.

Alberto Donato

unread,
Jul 28, 2008, 9:57:53 AM7/28/08
to Django developers
I have the same double-registration problem.
I've done different tests putting the callback registration in
different packages (i.e. myapp/__init__.py, myapp/models.py, myapp/
admin.py).

The result is different whether i put the definition of the callback
function in models.py, in myapp/init_.py or in the admin.py.

Putting callback definition in myapp/__init__.py and dispatcher
registration in models.py works (i.e. leads to a single call of the
callback function).

If I put some debug print in the callback function, I see it has 2
different IDs in the 2 calls, so I think there is some strange imports
problem (maybe relative/absolute imports mixed?) in django code that
tricks pydispatcher code making appear the same function as two
different ones.

On Jul 28, 3:14 pm, "James Bennett" <ubernost...@gmail.com> wrote:
> On Mon, Jul 28, 2008 at 7:04 AM, Alex Rades <alera...@gmail.com> wrote:
> > I've found an ugly workaround: putting thesignalregistration code
> > into admin.py ensures it is executed only once. (But it is only a
> > workaround since it ties thesignalregistration to the use of the
> > admin interface). I was previously putting thesignalregistration
> > code in app/models/__init__.py (which triggers the double
> > registration)
>
> I dosignal-registration stuff in model files all the time, and I've

Thomas Guettler

unread,
Jul 28, 2008, 11:00:59 AM7/28/08
to django-d...@googlegroups.com
Alex Rades schrieb:

> Hi,
> the problem is described here:
>
> 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?
>
>
Yes, I use them. I once had this double import problems, too. It was during
setting up the python logging module.

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

Jeremy Dunck

unread,
Jul 28, 2008, 11:04:59 AM7/28/08
to django-d...@googlegroups.com
On Mon, Jul 28, 2008 at 8:57 AM, Alberto Donato
<alberto...@gmail.com> wrote:
...

> If I put some debug print in the callback function, I see it has 2
> different IDs in the 2 calls, so I think there is some strange imports
> problem (maybe relative/absolute imports mixed?) in django code that
> tricks pydispatcher code making appear the same function as two
> different ones.

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?

Alberto Donato

unread,
Jul 28, 2008, 11:19:42 AM7/28/08
to django-d...@googlegroups.com
Tried the test, it actually prints out both 'mysite/myapp' and 'myapp'.
I never import 'myapp' directly, but always 'mysite/myapp'.

Malcolm Tredinnick

unread,
Jul 28, 2008, 12:54:32 PM7/28/08
to django-d...@googlegroups.com

On Mon, 2008-07-28 at 10:04 -0500, Jeremy Dunck wrote:
[...]

> I'd be a proponent of Django issuing a warning any time it's started
> with overlapping sys.path's.

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


Leo Soto M.

unread,
Jul 28, 2008, 1:11:17 PM7/28/08
to django-d...@googlegroups.com
On Mon, Jul 28, 2008 at 11:19 AM, Alberto Donato
<alberto...@gmail.com> wrote:
>
> Tried the test, it actually prints out both 'mysite/myapp' and 'myapp'.
> I never import 'myapp' directly, but always 'mysite/myapp'.

Maybe you put 'myapp' (without leading 'mysite.') on urls.py,
INSTALLED_APPS, or other declarative setting?

--
Leo Soto M.
http://blog.leosoto.com

Jeremy Dunck

unread,
Jul 28, 2008, 1:31:33 PM7/28/08
to django-d...@googlegroups.com
On Mon, Jul 28, 2008 at 11:54 AM, Malcolm Tredinnick
<mal...@pointy-stick.com> wrote:
>
>
> On Mon, 2008-07-28 at 10:04 -0500, Jeremy Dunck wrote:
> [...]
>> I'd be a proponent of Django issuing a warning any time it's started
>> with overlapping sys.path's.
>
> Um... yuk. :-(
...

> 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>).

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."

Malcolm Tredinnick

unread,
Jul 28, 2008, 1:40:29 PM7/28/08
to django-d...@googlegroups.com

On Mon, 2008-07-28 at 12:31 -0500, Jeremy Dunck wrote:
> On Mon, Jul 28, 2008 at 11:54 AM, Malcolm Tredinnick
> <mal...@pointy-stick.com> wrote:
> >
> >
> > On Mon, 2008-07-28 at 10:04 -0500, Jeremy Dunck wrote:
> > [...]
> >> I'd be a proponent of Django issuing a warning any time it's started
> >> with overlapping sys.path's.
> >
> > Um... yuk. :-(
> ...
> > 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>).
>
> 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 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


Leo Soto M.

unread,
Jul 29, 2008, 5:13:38 PM7/29/08
to django-d...@googlegroups.com
On Mon, Jul 28, 2008 at 1:40 PM, Malcolm Tredinnick

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.

Reply all
Reply to author
Forward
0 new messages