This issue tracker has been migrated to GitHub ,
and is currently read-only.
For more information,
see the GitHub FAQs in the Python's Developer Guide.
Created on 2014年05月22日 15:37 by mythsmith, last changed 2022年04月11日 14:58 by admin. This issue is now closed.
| Files | ||||
|---|---|---|---|---|
| File name | Uploaded | Description | Edit | |
| imptest.zip | mythsmith, 2014年05月22日 15:37 | imptest package exposing import inconsistencies | ||
| Messages (3) | |||
|---|---|---|---|
| msg218901 - (view) | Author: mythsmith (mythsmith) | Date: 2014年05月22日 15:37 | |
I found a condition where different behaviour could be observed depending on how a module is imported.
It seems to be different to write:
import module
# against:
from package import module
In the attachment you find a minimal package (imptest) with this organization:
imptest
|-> __init__.py (empty)
|-> m.py (module which initializes a variable "foo=0")
|- sub (package)
|-> __init__.py (empty)
|-> subm.py (module which, upon import, changes "m.foo=1")
And two scripts which can be directly executed:
|-> run0.py (using "import m")
|-> run1.py (using "from imptest import m")
Contents of the module m:
#########################
foo=0
def do():
global foo
foo=1
print('doing foo=',foo)
print("imported foo=",foo)
Contents of module subm:
#######################
from imptest import m
from imptest import m
print("imported sub, foo=",m.foo)
Both run0.py and run1.py imports module m and calls the do() function, thus theoretically changing foo to 1.
Both later import the subm module, which in turn imports again the m module. What I would expect is that,
since m is already in memory, it is not really imported again: so foo remains equal to 1 also after subm import.
I found that this actually depends on how I imported m in the script.
Contents of run0.py:
####################
import m
m.do()
print("importing subm")
from imptest.sub import subm
Result:
imported m; foo= 0
doing foo= 1
importing subm
imported m; foo= 0
imported sub, foo= 0
As you can see from printout "importing subm", the m module is imported again and thus foo is reset to 0. In run1.py,
I changed the line "import m" to "from imptest import m", and got the expected behaviour:
Contents of run1.py:
####################
from imptest import m
m.do()
print("importing subm")
from imptest.sub import subm
Result:
imported m; foo= 0
doing foo= 1
importing subm
imported sub, foo= 1
I know that directly running a module in the first level of a package may seem strange or not correct, but could someone explain why this is happening?
I would expect a module to be loaded in memory at the first import and then referred in any way I later or elsewhere in the program choose to import it.
|
|||
| msg218903 - (view) | Author: Peter Otten (peter.otten) * | Date: 2014年05月22日 17:17 | |
Here's a simpler demo for what I believe you are experiencing: $ mkdir package $ cd package/ $ touch __ini__.py module.py $ export PYTHONPATH=.. $ python3 Python 3.3.2+ (default, Feb 28 2014, 00:52:16) [GCC 4.8.1] on linux Type "help", "copyright", "credits" or "license" for more information. >>> import module, package.module >>> module is package.module False Even though module and package.module correspond to the same file Python does not recognize that you intend the former to be part of a package. Your run0.py script goes through its sys.path entries and unfortunately the first entry points into a package so that all modules in that package become also visible as toplevel modules. A good way to avoid this trap is to use relative imports >>> from . import module Traceback (most recent call last): File "<stdin>", line 1, in <module> SystemError: Parent module '' not loaded, cannot perform relative import |
|||
| msg218905 - (view) | Author: Eric Snow (eric.snow) * (Python committer) | Date: 2014年05月22日 17:41 | |
This is a consequence of a script's directory getting prepended to sys.path. See issue #13475. |
|||
| History | |||
|---|---|---|---|
| Date | User | Action | Args |
| 2022年04月11日 14:58:03 | admin | set | github: 65752 |
| 2014年05月23日 00:29:13 | berker.peksag | set | superseder: Add '--mainpath'/'--nomainpath' command line options to override sys.path[0] initialisation |
| 2014年05月22日 17:41:38 | eric.snow | set | status: open -> closed resolution: duplicate messages: + msg218905 stage: resolved |
| 2014年05月22日 17:17:26 | peter.otten | set | nosy:
+ peter.otten messages: + msg218903 |
| 2014年05月22日 15:44:32 | ezio.melotti | set | nosy:
+ brett.cannon, ncoghlan, eric.snow |
| 2014年05月22日 15:37:33 | mythsmith | create | |