如果我将脚本命名为 '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
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:
The home directory of the program
PYTHONPATH directories (if set)
Standard library directories
The contents of any .pth files (if present)
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
更新:
案例 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
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:
The home directory of the program
PYTHONPATH directories (if set)
Standard library directories
The contents of any .pth files (if present)
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