Two instances of the same Python module?

I created a Python module with a single function that just prints 'a!'. I opened the Python interpreter and imported the module in 2 different syntaxes

>>> import a >>> from a import func >>> func() a! >>> a.func() a! 

At that moment I changed the function to print something else and then appreciated again

 >>> func() a! >>> a.func() a! 

This, of course, is expected since the module was not rebooted. Then I reloaded the module and expected both functions to be updated:

 >>> reload(a) <module 'a' from 'a.py'> >>> a.func() aasd! >>> func() a! 

Only a.func seems to be updating. I always thought that Python only stores one instance of the same module, but now it seems to be two. I conducted additional testing to verify my claim, and added a print instruction at the top level of the module, then restarted the interpreter again and imported again:

 >>> import a module imported >>> import a >>> from a import func 

This bothers me even more, as I was expecting to β€œimport the module” twice. The third experiment I did was a global variable experiment:

 >>> import a module imported >>> from a import GLOBAL_VAR >>> GLOBAL_VAR = 5 >>> a.GLOBAL_VAR 1 >>> GLOBAL_VAR 5 >>> GLOBAL_VAR is a.GLOBAL_VAR False 

So, there is one instance of the module, but different instances of the objects inside? How can I implement Gevent monkey patching with this behavior?

+6
source share
4 answers

A module, after importing it, is another python object. Therefore, seeing the following example, your results should not surprise you:

 x = SomeObject() xy = 1 a = xy xy = 2 print(a) #a is still 1, not 2 

When you execute from module import name , a name variable is created in the current namespace that contains a link to the imported thing (be it package / module / class / independently). This is syntactic sugar for the following:

 import module name = module.name 

Now when you reload module , you obviously are not updating the name link.

As for your second experiment, the module is cached in sys.modules after import; subsequent import will use the cache. Thus, all code that is directly at the module level, for example your print , will only be executed on the first import.

+6
source

When you reload the module, all functions that are reloaded in the current module. But when you import a specific function from a module, it becomes local to the current module. Thus, a change in one will not affect the other.

Check this:

 import math from math import factorial print locals() print id(math.factorial), id(factorial) math.factorial, factorial = 0, 1 print id(math.factorial), id(factorial) reload(math) print id(math.factorial), id(factorial) from math import factorial print id(math.factorial), id(factorial) 

Output

 {'__builtins__': <module '__builtin__' (built-in)>, '__file__': '/home/thefourtheye/Desktop/Test.py', '__package__': None, 'factorial': <built-in function factorial>, # Factorial is in the local context '__name__': '__main__', '__doc__': None, 'math': <module 'math' (built-in)>} 39346504 39346504 33545712 33545688 39346504 33545688 39346504 39346504 

id prints the address of an object in memory in a CPython implementation

+2
source

I just confirmed that a specific Python session ensures that there is only one instance of a particular module (more specifically the file path).

Proof (using one Python session):

foobar.py:

 a = 123 def foo(): print a 

Python:

 >>> from foobar import foo >>> foo() 123 

Modifying foobar.py:

 a = 1234 def foo(): print a;print a 

Python:

 >>> reload(foobar) <module 'foobar' from 'c:\foobar.py'> >>> foobar.foo() 1234 1234 >>> foo() 1234 >>> id(sys.modules[foo.__module__]) == id(sys.modules[foobar.foo.__module__]) True 

The only thing that causes different outputs is the code object, ( foo.__globals['a'] and foobar.foo.__globals__['a'] is the same)

 >>> id(foo.__code__) == id(foobar.foo.__code__) False 

Do not know how to patch Gevent monkey.

0
source

In Python, variables are names, not containers. All this is an object, all references, but variables are not. Variables refer to objects and namespaces namespaces for objects. You can use the module to organize the code, each module is executed during the first import.

So, after importing a as b, b refer to object a, a will remain unchanged unless you change object a (if it is changed). When you reload (a), you simply assign one new object to a variable that has nothing to do with b at all.

 >>> a = 1 >>> b = a >>> a = 2 >>> print b 1 >>> import a >>> from a import func >>> id(func) 4324575544 >>> id(a.func) 4324575544 >>> reload(a) <module 'a' from 'a.py'> >>> id(a.func) 4324576624 >>> id(func) 4324575544 
-1
source

All Articles