Python defines my class twice on the same thread - python

I had assumed that in Python if I do some
class A:
print("hi")
this "hi" would only ever be printed more than once if I explicitly deleted A with some del A
In my slightly bigger project I have this code (names changed):
class A(ISomething):
print(threading.current_thread())
try:
A.MY_DICT # yeah, this should never ever result in anything but an error but neither should this code be run twice
print(A.MY_DICT)
except NameError:
print("A.MY_DICT unknown")
MY_DICT = {}
and it produces this output:
$ python main.py
<_MainThread(MainThread, started 140438561298240)>
A.MY_DICT unknown
<_MainThread(MainThread, started 140438561298240)>
A.MY_DICT unknown
so on the same thread the same class level code gets executed twice. How is that possible when I never del A? The code had worked before but I don't have commits to narrow down the change that broke it.
The same code with MY_DICT instead of A.MY_DICT fails equally and as PyDev already at time of writing tells me that this will not work, I am pretty confident that there's something fishy going on.

You are probably importing the file under different names, or running it as both the __main__ file and importing it.
When Python runs your script (the file named on the command line) it gives it the name __main__, which is a namespace stored under sys.modules. But if you then import that same file using an import statement, it'll be run again and the resulting namespace is stored under the module name.
Thus, python main.py where main.py includes an import main statement or imports other code that then in turn imports main again will result in all the code in main.py to be run twice.
Another option is that you are importing the module twice under different full names; both as part of a package and as a stand-alone module. This can happen when both the directory that contains the package and the package itself are listed on your sys.path module search path.

Related

from script import function runs everything? [duplicate]

I'm new to python and doing an assignment. It's meant to be done with linux but as I'm doing it by myself on my own computer I'm doing it on windows.
I've been trying to do this test system that we use looking like this:
>>> import file
>>> file.function(x)
"Answer that we want"
Then we run it through the linux terminal. I've been trying to create my own way of doing this by making a test file which imports the file and runs the function. But then on the other hand of just running the function it runs the whole script. Even though it's never been called to do that.
Import file
file.function(x)
That's pretty much what I've been doing but it runs the whole "file". I've also tried from file import function; it does the same.
What kind of script can I use to script the "answer that I want" for the testfile? As when we run in through linux terminal it says if it has failed or scored.
importing a file is equivalent to running it.
When you import a file (module), a new module object is created, and upon executing the module, every new identifier is put into the object as an attribute.
So if you don't want the module to do anything upon importing, rewrite it so it only has assignments and function definitions.
If you want it to run something only when invoked directly, you can do
A = whatever
def b():
...
if __name__ == '__main__'
# write code to be executed only on direct execution, but not on import
# This is because direct execution assigns `'__main__'` to `__name__` while import of any way assigns the name under which it is imported.
This holds no matter if you do import module or from module import function, as these do the same. Only the final assignment is different:
import module does:
Check sys.modules, and if the module name isn't contained there, import it.
Assign the identifier module to the module object.
from module import function does
Check sys.modules, and if the module name isn't contained there, import it. (Same step as above).
Assign the identifier function to the module object's attribute function.
You can check if the module is imported or executed with the __name__ attribute. If the script is executed the attribute is '__main__'.
It is also good style to define a main function that contains the code that should be executed.
def main()
# do something
pass
if __name__ == '__main__'
main()

Win10 Python 3.7: Change in Implicit Relative Imports since First Versions of Python 3?

I see in several old questions that around the switch from Python 2 to Python 3, implicit relative imports were not allowed. However, I ran into a problem that seems to suggest they do happen and am wondering if something changed or if my understanding is incorrect. Edit: To clarify, I thought the below would not be an implicit relative import, but it seems to act like it.
I made an empty file called queue.py and another file called uses_queue.py which contains:
from multiprocessing import Queue
q = Queue()
which crashes on execution saying ImportError: cannot import name 'Empty' from 'queue' however it will not crash if I delete that aforementioned empty file called queue.py. Changing from multiprocessinging to from .multiprocessing or _multiprocessing or ._multiprocessing which didn't change anything.

When importing a function it runs the whole script?

I'm new to python and doing an assignment. It's meant to be done with linux but as I'm doing it by myself on my own computer I'm doing it on windows.
I've been trying to do this test system that we use looking like this:
>>> import file
>>> file.function(x)
"Answer that we want"
Then we run it through the linux terminal. I've been trying to create my own way of doing this by making a test file which imports the file and runs the function. But then on the other hand of just running the function it runs the whole script. Even though it's never been called to do that.
Import file
file.function(x)
That's pretty much what I've been doing but it runs the whole "file". I've also tried from file import function; it does the same.
What kind of script can I use to script the "answer that I want" for the testfile? As when we run in through linux terminal it says if it has failed or scored.
importing a file is equivalent to running it.
When you import a file (module), a new module object is created, and upon executing the module, every new identifier is put into the object as an attribute.
So if you don't want the module to do anything upon importing, rewrite it so it only has assignments and function definitions.
If you want it to run something only when invoked directly, you can do
A = whatever
def b():
...
if __name__ == '__main__'
# write code to be executed only on direct execution, but not on import
# This is because direct execution assigns `'__main__'` to `__name__` while import of any way assigns the name under which it is imported.
This holds no matter if you do import module or from module import function, as these do the same. Only the final assignment is different:
import module does:
Check sys.modules, and if the module name isn't contained there, import it.
Assign the identifier module to the module object.
from module import function does
Check sys.modules, and if the module name isn't contained there, import it. (Same step as above).
Assign the identifier function to the module object's attribute function.
You can check if the module is imported or executed with the __name__ attribute. If the script is executed the attribute is '__main__'.
It is also good style to define a main function that contains the code that should be executed.
def main()
# do something
pass
if __name__ == '__main__'
main()

Modules imported twice. Possible bug in Python interpreter

I've made a rather contrived import scheme in a project of mine and I think I might have discovered a bug in the Python interpreter that causes modules to be imported twice.
Here's how my test project is set up:
/
Launcher.bat — Project is run from here. It launches 'main/__init__.py` using the Python 3.2 executable
main/__init__.py — The __main__ script, the one launched by 'Launcher.bat'
main/foo.py — Contains an empty class
external/__init__.py — A script external to the 'main' project scripts, used to demonstrate the problem
./Launcher.bat
#echo off
C:\Python32\python.exe main\__init__.py
pause
./main/__init__.py
from foo import Foo
print("In 'main', Foo has id:", id(Foo))
# Add the directory from which 'Launcher.bat' was run,
# which is not the same as the './main' directory
# in which this script is located
import sys
sys.path.insert(1, '.')
# This script will try to import class Foo, but in doing so
# will casue the interpreter to import this './main/__init__.py'
# script a second time.
__import__('external')
./main/foo.py
class Foo:
pass
./external/__init__.py
from main.foo import Foo
print("In 'external', Foo has id:", id(Foo))
All of this will print the 'Main script was imported' message twice. If the external script imports any other scripts, those too will be imported twice. I've only tested this on Python 3.2. Is this a bug, or did I make a mistake?
Output of the program is:
In 'main', Foo has id: 12955136
In 'main', Foo has id: 12955136
In 'external', Foo has id: 12957456
Press any key to continue . . .
I don't think it's a bug. You should ask on the python-dev list for a more authoritative answer. You are executing once (when you run the script) and importing once (from external) so the line gets printed twice. It's not importing twice.
However, this is a horrible setup. There are a lot of style violations here. Granted that some are for demonstration purposes only, it's still quite messy.
You shouldn't use a package __init__.py file as a file which should be run. The main entry point should be a script that imports the package.
You shouldn't have an imported module importing the module which imported it. Like you external is doing to main.
The first print is misleading: Since you're not importing, but executing the file at the first time (__name__ == '__main__' holds true), the main modules just gets imported once. Move the start point into a secondary file, or check for __name__ == '__main__'.
By the way, circular import are a bad idea. You should resolve the circular import (by moving foo to a dedicated library). Alternatively, you can make your modules reentrant (i.e. check for the current directory being in sys.path before adding it).

How to prevent a module from being imported twice?

When writing python modules, is there a way to prevent it being imported twice by the client codes? Just like the c/c++ header files do:
#ifndef XXX
#define XXX
...
#endif
Thanks very much!
Python modules aren't imported multiple times. Just running import two times will not reload the module. If you want it to be reloaded, you have to use the reload statement. Here's a demo
foo.py is a module with the single line
print("I am being imported")
And here is a screen transcript of multiple import attempts.
>>> import foo
Hello, I am being imported
>>> import foo # Will not print the statement
>>> reload(foo) # Will print it again
Hello, I am being imported
Imports are cached, and only run once. Additional imports only cost the lookup time in sys.modules.
As specified in other answers, Python generally doesn't reload a module when encountering a second import statement for it. Instead, it returns its cached version from sys.modules without executing any of its code.
However there are several pitfalls worth noting:
Importing the main module as an ordinary module effectively creates two instances of the same module under different names.
This occurs because during program startup the main module is set up with the name __main__. Thus, when importing it as an ordinary module, Python doesn't detect it in sys.modules and imports it again, but with its proper name the second time around.
Consider the file /tmp/a.py with the following content:
# /tmp/a.py
import sys
print "%s executing as %s, recognized as %s in sys.modules" % (__file__, __name__, sys.modules[__name__])
import b
Another file /tmp/b.py has a single import statement for a.py (import a).
Executing /tmp/a.py results in the following output:
root#machine:/tmp$ python a.py
a.py executing as __main__, recognized as <module '__main__' from 'a.py'> in sys.modules
/tmp/a.pyc executing as a, recognized as <module 'a' from '/tmp/a.pyc'> in sys.modules
Therefore, it is best to keep the main module fairly minimal and export most of its functionality to an external module, as advised here.
This answer specifies two more possible scenarios:
Slightly different import statements utilizing different entries in sys.path leading to the same module.
Attempting another import of a module after a previous one failed halfway through.

Categories

Resources