导入或不导入模块时执行行为之间的区别
Difference between exec behavior when module is imported or not
我是以下节目的 运行。重要的是,假设在这两个程序所在的目录中有 mymodule.py
文件。
第一个:
exec('''import sys
import os
os.chdir('/')
sys.path = []
import mymodule''', {})
第二个:
import mymodule
exec('''import sys
import os
os.chdir('/')
sys.path = []
import mymodule''', {})
第一个片段引发了ImportError
的预期(毕竟mymodule所在的目录不在path中)。然而,第二个片段没有,即使 mymodule 也不在它的路径中并且我给它的环境是空的。
我的问题是为什么
根据The import system - The module cache,
The first place checked during import search is sys.modules
. This
mapping serves as a cache of all modules that have been previously
imported, including the intermediate paths. So if foo.bar.baz was
previously imported, sys.modules will contain entries for foo,
foo.bar, and foo.bar.baz. Each key will have as its value the
corresponding module object.
During import, the module name is looked up in sys.modules
and if
present, the associated value is the module satisfying the import, and
the process completes. However, if the value is None, then a
ModuleNotFoundError is raised. If the module name is missing, Python
will continue searching for the module.
第二个片段导入成功mymodule
;它缓存在 sys.modules
中,因此不会在其他地方进行搜索。
这与 exec()
无关,只是对 运行 脚本以及 Python 看起来时 sys.path
上可用内容的简单误解用于加载文件。
您说:
I am running to of the following programs. Importantly, imagine that there is mymodule.py
file in the directory where both these programs are located.
[...]
The second snippet, however, does not, even though mymodule is also not in its path
模块在其路径上。您的脚本所在的目录被添加到模块搜索路径的开头。见 Command line:
<script>
Execute the Python code contained in script, which must be a filesystem path (absolute or relative) referring to either a Python file, a directory containing a __main__.py
file, or a zipfile containing a __main__.py
file.
[...]
If the script name refers directly to a Python file, the directory containing that file is added to the start of sys.path
, and the file is executed as the __main__
module.
大胆强调我的。
因此,您声明的 mymodule.py
与您的脚本 运行 位于同一目录中,就在路径上。
加载后,模块保持加载。如果 sys.modules
中还没有同名模块,import <module>
只会查看模块搜索路径。使用 exec
或不进行导入都没有关系。
来自import
statement documentation:
The basic import
statement (no from clause) is executed in two steps:
- find a module, loading and initializing it if necessary
- define a name or names in the local namespace for the scope where the
import
statement occurs.
如有必要部分是重要的部分。
此外,来自The import system:
The import
statement combines two operations; it searches for the named module, then it binds the results of that search to a name in the local scope.
[...]
When a module is first imported, Python searches for the module and if found, it creates a module object, initializing it.
The first place checked during import search is sys.modules
. This mapping serves as a cache of all modules that have been previously imported, including the intermediate paths. So if foo.bar.baz
was previously imported, sys.modules
will contain entries for foo
, foo.bar
, and foo.bar.baz
. Each key will have as its value the corresponding module object.
During import, the module name is looked up in sys.modules
and if present, the associated value is the module satisfying the import, and the process completes.
所以当您的 exec()
代码运行时,第一个 import mymodule
已经成功并且 sys.modules[
mymodule] exists. The second
import mymodule` 找到了那个对象,并且搜索结束。
我是以下节目的 运行。重要的是,假设在这两个程序所在的目录中有 mymodule.py
文件。
第一个:
exec('''import sys
import os
os.chdir('/')
sys.path = []
import mymodule''', {})
第二个:
import mymodule
exec('''import sys
import os
os.chdir('/')
sys.path = []
import mymodule''', {})
第一个片段引发了ImportError
的预期(毕竟mymodule所在的目录不在path中)。然而,第二个片段没有,即使 mymodule 也不在它的路径中并且我给它的环境是空的。
我的问题是为什么
根据The import system - The module cache,
The first place checked during import search is
sys.modules
. This mapping serves as a cache of all modules that have been previously imported, including the intermediate paths. So if foo.bar.baz was previously imported, sys.modules will contain entries for foo, foo.bar, and foo.bar.baz. Each key will have as its value the corresponding module object.During import, the module name is looked up in
sys.modules
and if present, the associated value is the module satisfying the import, and the process completes. However, if the value is None, then a ModuleNotFoundError is raised. If the module name is missing, Python will continue searching for the module.
第二个片段导入成功mymodule
;它缓存在 sys.modules
中,因此不会在其他地方进行搜索。
这与 exec()
无关,只是对 运行 脚本以及 Python 看起来时 sys.path
上可用内容的简单误解用于加载文件。
您说:
I am running to of the following programs. Importantly, imagine that there is
mymodule.py
file in the directory where both these programs are located.[...]
The second snippet, however, does not, even though mymodule is also not in its path
模块在其路径上。您的脚本所在的目录被添加到模块搜索路径的开头。见 Command line:
<script>
Execute the Python code contained in script, which must be a filesystem path (absolute or relative) referring to either a Python file, a directory containing a
__main__.py
file, or a zipfile containing a__main__.py
file.[...]
If the script name refers directly to a Python file, the directory containing that file is added to the start of
sys.path
, and the file is executed as the__main__
module.
大胆强调我的。
因此,您声明的 mymodule.py
与您的脚本 运行 位于同一目录中,就在路径上。
加载后,模块保持加载。如果 sys.modules
中还没有同名模块,import <module>
只会查看模块搜索路径。使用 exec
或不进行导入都没有关系。
来自import
statement documentation:
The basic
import
statement (no from clause) is executed in two steps:
- find a module, loading and initializing it if necessary
- define a name or names in the local namespace for the scope where the
import
statement occurs.
如有必要部分是重要的部分。
此外,来自The import system:
The
import
statement combines two operations; it searches for the named module, then it binds the results of that search to a name in the local scope.[...]
When a module is first imported, Python searches for the module and if found, it creates a module object, initializing it.
The first place checked during import search is
sys.modules
. This mapping serves as a cache of all modules that have been previously imported, including the intermediate paths. So iffoo.bar.baz
was previously imported,sys.modules
will contain entries forfoo
,foo.bar
, andfoo.bar.baz
. Each key will have as its value the corresponding module object.During import, the module name is looked up in
sys.modules
and if present, the associated value is the module satisfying the import, and the process completes.
所以当您的 exec()
代码运行时,第一个 import mymodule
已经成功并且 sys.modules[
mymodule] exists. The second
import mymodule` 找到了那个对象,并且搜索结束。