Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/313.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在python中清除sys.path之后,导入如何工作?_Python_Python 3.x - Fatal编程技术网

在python中清除sys.path之后,导入如何工作?

在python中清除sys.path之后,导入如何工作?,python,python-3.x,Python,Python 3.x,因此,我正在学习Python模块,根据我的理解,当我们尝试导入代码中的模块时,Python会查看该模块是否存在于sys.path中,如果不存在,则会引发ModuleNotFoundError 将位置添加到系统路径 因此,假设我想从一个默认情况下不存在于sys.path中的位置导入,我可以简单地将这个新位置附加到sys.path中,一切正常,如下面的代码片段所示 ~/Documents/python modules/usemymodule.py ~/Documents/python模块/modul

因此,我正在学习Python模块,根据我的理解,当我们尝试导入代码中的模块时,Python会查看该模块是否存在于sys.path中,如果不存在,则会引发
ModuleNotFoundError

将位置添加到系统路径 因此,假设我想从一个默认情况下不存在于
sys.path
中的位置导入,我可以简单地将这个新位置附加到
sys.path
中,一切正常,如下面的代码片段所示

~/Documents/python modules/usemymodule.py

~/Documents/python模块/modules/mymodule.py

清除
sys.path
我的疑问是,当我清除整个
sys.path
列表时,我应该无法导入任何模块,但出乎意料的是,我仍然可以导入内置的模块。下面的代码工作正常

import sys
sys.path.clear()

import math
math.ceil(10.2)
我认为python内部可能不使用
sys.path
sys.path
只是python使用的原始列表的一个简单副本,但是添加到
sys.path
如何工作,为什么清除后我只能导入内置模块而不能导入自定义模块

我真的被卡住了,任何帮助都会很好。还有一个类似的问题,但它不能回答我的疑问


CPython有一个内置模块列表,如文件中定义的math,如下所示:

struct\u inittab\u PyImport\u inittab[]={
{u abc,PyInit_abc},
{“数组”,PyInit_数组},
{u ast,PyInit{u ast},
{“audioop”,PyInit_audioop},
{“binascii”,PyInit_binascii},
{“cmath”,PyInit_cmath},
...
};
因此,当它需要导入内置模块时,它会查看此列表。列表中的每个“PyInit”函数都返回内存中的模块对象

然后,此列表显示为系统内置模块名称,在中初始化。然后,调用
importlib.\u bootstrap.\u find\u spec
中的导入代码,并查看
sys.meta\u path
中的导入工厂列表。其中一个是importlib.\u bootstrap.BuiltinImporter,它负责导入内置模块。这演示了
sys.meta\u路径

导入系统 >>>sys.modules['math'] >>>sys.path.clear() >>>导入数学#这是因为数学在模块缓存中。 >>>del sys.modules['math'] >>>导入数学#由于sys.meta#u路径中的内置端口,这项工作正常! >>>sys.meta_path.clear() >>>导入数学#这仍然有效,因为数学在模块缓存中。 >>>del sys.modules['math'] >>>导入数学#此操作失败,因为我们清除了sys.meta_路径! 回溯(最近一次呼叫最后一次): 文件“”,第1行,在 ModuleNotFoundError:没有名为“math”的模块 这是在蟒蛇3.7上运行的-在不同的发行版下可能会有所不同

我想补充一点,您的测试没有考虑
sys.modules
中的模块缓存。用非构建模块来考虑这个例子:

导入请求 >>>导入系统 >>>sys.path.clear() >>>导入请求#这很有效! >>>删除系统模块['requests'] >>>导入请求#这不是。 回溯(最近一次呼叫最后一次): 文件“”,第1行,在 ModuleNotFoundError:没有名为“requests”的模块
我试图重现您的示例,但出乎意料的是没有得到相同的结果(注意:这里是python3.9)

导入系统 sys.path.clear() 输入数学 回溯(最近一次呼叫最后一次): 文件“”,第1行,在 ModuleNotFoundError:没有名为“math”的模块
但是,这个有效:

import math
del math

import sys
sys.path.clear()

import math

# but removing the reference in sys.modules will break the import again
del sys.modules['math']
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ModuleNotFoundError: No module named 'math'
导入数学
德尔马
导入系统
sys.path.clear()
输入数学
#但是删除sys.modules中的引用将再次中断导入
del sys.modules['math']
回溯(最近一次呼叫最后一次):
文件“”,第1行,在
ModuleNotFoundError:没有名为“math”的模块

我的猜测是,解释器保留了以前导入时对数学模块的引用,因此不需要在
sys.path

中搜索它。如果
内置的
东西以某种方式内置在python解释器中,那不是很好吗?所以不需要真正的源文件?不确定是否会是这样。。。但我的猜测是看看python解释器本身所在的位置。看@PatrickArtner我真的不明白你的意思。你是在告诉我在清除之前,看看
math.py
在哪里,如果是这样的话,那么它位于
/usr/lib/python3.8
,在
sys.path
中有一个条目。我最好的猜测是python在二进制文件中内置了一个位置,例如
/usr/lib/python$python\u VERSION
,当
sys.path
为空时,将其用作回退。这是否回答了您的问题@python_用户不,绝对不是!可以因此,如果我清楚地理解您的意思,如果我在清除
sys.path
后尝试导入请求
,它将引发ModuleNotFoundError。是的,但前提是您也先将其从缓存中删除。这很奇怪,因为我只是在没有清除缓存的情况下尝试导入请求,它仍然会引发异常。我所做的就是:
importsys;sys.path.clear();导入请求
请注意,
PC/config.c
是为Windows版本定义该列表的地方。在其他平台上,列表位于从生成的
config.c
中。@SomShekharMukherjee我更新了我的答案,提供了有关
sys.meta_path
的详细信息。在Python 3.9.5上尝试了这一点,它适用于MeInterest——我和Python聊天中的一些人得到了相互矛盾的结果,即使我们有相同的版本。也许这是操作系统的问题。
import sys
sys.path.clear()

import math
math.ceil(10.2)
import sys
sys.path.clear()

import math
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ModuleNotFoundError: No module named 'math'
import math
del math

import sys
sys.path.clear()

import math

# but removing the reference in sys.modules will break the import again
del sys.modules['math']
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ModuleNotFoundError: No module named 'math'