8

Recently I had an issue where a signal I was using from flask-security was not behaving as expected in python 3.3. In looking at the source code for flask-security I noticed that the signal I was importing from a module in the flask-security package was also imported in __init__.py. By importing the signal from the top level of the package I was able to solve my problem (since the signal gets imported when package is initialized).

If I run the following code:

from flask.ext.security import user_registered
from flask.ext.security.signals import user_registered as user_reg_sig
user_registered==user_reg_sig

I'll get True in python 2.7 and I'll get False for python 3.3+.

What is different in python 3.3+ that causes this difference in import behaviour?

EDIT: I'm still stumped by the python 2.7 vs 3.3+ issue, but have managed to narrow down that the issue is occurring when the __init__.py of flask.ext is called and uses the ExtensionImporter class from exthook.py to import flask-security.

Running the following under python 3.4 returns True when flask-security is directly imported avoiding the extension hook:

from flask_security.signals import user_registered as user_reg_sig
from flask_security import user_registered
user_registered==user_reg_sig

Here is repr() for signals for flask.ext.security and flask_security examples:

from flask_security.signals import user_registered as user_reg_sig
from flask_security import user_registered

repr(user_registered)
>>> "<blinker.base.NamedSignal object at 0x7fb38e258400; 'user-registered'>"

repr(user_reg_sig)
>>> "<blinker.base.NamedSignal object at 0x7fb38e258400; 'user-registered'>"

from flask.ext.security import user_registered
from flask.ext.security.signals import user_registered as user_reg_sig

repr(user_registered)
>>> "<blinker.base.NamedSignal object at 0x7fb38e258400; 'user-registered'>"

repr(user_reg_sig)
>>> "<blinker.base.NamedSignal object at 0x7fb38dd030b8; 'user-registered'>"
Community
  • 1
  • 1
khammel
  • 2,047
  • 1
  • 14
  • 18
  • And if you print out the repr of each? – Ignacio Vazquez-Abrams Sep 08 '15 at 20:43
  • Added the repr within the question. So definitely a different object when accessed through flask.ext. – khammel Sep 08 '15 at 21:12
  • I guess it has something to do with [http://stackoverflow.com/questions/4798589/what-could-cause-a-python-module-to-be-imported-twice] and the changes in Python3.3 in that area. Also read this [http://python-notes.curiousefficiency.org/en/latest/python_concepts/import_traps.html]. – mkiever Sep 09 '15 at 16:18

1 Answers1

0

There are multiple cases where Python can decide to create a new instance of an object when you re-import the module.

In fact that's not even Python 3 specific and it can happen in various scenarios.

Mainly you have to assume that the two objects may be different and work around this.

sorin
  • 161,544
  • 178
  • 535
  • 806
  • Thanks. Seems like there is a bit of an issue with the use of signals by Flask and what happens when imports happen through flask.ext.* – khammel Sep 16 '15 at 12:53