如果我将脚本命名为 'string.py' 或 'math.py','import' 操作的行为会有所不同。为什么会这样?

'import' operation behaves differently if I name script 'string.py' or 'math.py'. Why it so?

更新:

案例 1:

同一文件夹中的文件数:

main.py

string.py

代码在main.py:

import string

代码在string.py:

print('Hello!')

运行 main.py 输出为:Hello!

案例 2:

同一文件夹中的文件数:

main.py

math.py

代码在main.py:

import math

代码在math.py:

print('Hello!')

运行 main.py 输出什么都没有...

老问题:

如果我将我的脚本命名为 'string.py' 并将其导入另一个脚本,它会与内置 'string' 模块重叠

如果我将我的脚本命名为 'math.py' 并将其导入另一个脚本,内置的 'math' 会与我自己的

重叠

使用内置模块等名称导入脚本的行为取决于我如何命名它们。

一些受影响的模块名称:hashlib、string、calendar

不影响的模块名称:math、cmath、os

来自realpython.com

The first thing Python will do is look up the name abc in sys.modules. This is a cache of all modules that have been previously imported. If the name isn’t found in the module cache, Python will proceed to search through a list of built-in modules. These are modules that come pre-installed with Python and can be found in the Python Standard Library. If the name still isn’t found in the built-in modules, Python then searches for it in a list of directories defined by sys.path.

来自 Michael Lutz 的“学习 Python”:

Roughly, Python’s module search path is composed of the concatenation of these major components, some of which are preset for you and some of which you can tailor to tell Python where to look:

  1. The home directory of the program

  2. PYTHONPATH directories (if set)

  3. Standard library directories

  4. The contents of any .pth files (if present)

  5. The site-packages home of third-party extensions

那么现在哪一个是正确的?

数学和字符串之间的区别在于数学是用 C 编写的以提高速度,而字符串模块是用 Python 编写的,可以在 python lib 目录下找到。

因此,当您尝试导入字符串时,本地文件将覆盖全局字符串文件,但是当您尝试导入数学时 Python 将不会搜索文件,因为它内置于Python 口译员。

您可以通过以下代码找到所有内置模块的列表:

import sys
print(sys.builtin_module_names)

如果您真的想覆盖数学模块,可以通过更改 sys.modules 字典中的值来实现。

我不相信@ZacharyaHaitin 的回答是正确的,而且我很确定如果 Karen 确实看到了问题中描述的行为,那么一定有其他事情发生了。

让我们运行通过一些例子...

覆盖 string 模块

我们有一个包含两个文件的空目录:

$ ls
main.py string.py

文件 main.py 包含:

$ cat main.py
import string

文件 string.py 包含:

$ cat math.py
print('hello')

当我们运行main.py时,我们看到:

$ python main.py
hello

覆盖 math 模块

如果我们用 math 进行相同的实验,我们会看到相同的行为。这里是 main.py:

$ cat main.py
import math

这里是 math.py:

$ cat math.py
print('hello')

当我们 运行 main.py 时,我们看到的行为与我们在前面的示例中看到的相同:

$ python main.py
hello

以上示例与 Python2 和 Python3 的行为相同。在这两种情况下都没有必要乱搞 sys.modules.


这是一个将重现上述示例的脚本:

#!/bin/sh

echo "Overriding string module"

cat > main.py << EOF
import string
EOF

cat > string.py <<EOF
print('hello')
EOF

echo "main.py"
echo "-------"
cat main.py
echo

echo "string.py"
echo "---------"
echo
cat string.py
echo

echo "Running main.py..."
python main.py

cat <<EOF

======================================================================

EOF

echo "Overriding math module"

cat > main.py << EOF
import math
EOF

cat > math.py <<EOF
print('hello')
EOF

echo "main.py"
echo "-------"
cat main.py
echo

echo "math.py"
echo "---------"
echo
cat math.py
echo

echo "Running main.py..."
python main.py