如何防范意外影子标准库?

问题描述 投票:0回答:1

我是 Python 新手,编写了一个实用程序脚本来生成一些我需要的数字。我将文件命名为

numbers.py
。该脚本依赖于 PyGame 库。我发现仅仅导入该库就会导致错误,因为 PyGame 尝试从 Python 标准库中
import numbers
,并且默认查找规则有我自己的文件隐藏标准库。

我尝试过的 linters(PyLint、Ruff)似乎没有发现我的这个菜鸟错误,但我很难理解如何最好地避免它。据我所知,“仅重命名文件”以免与标准库冲突的建议需要:

  1. 记住 307 个标准库名称(没有句点;总共 1027 个名称),或者
  2. 能够通过其他库的错误识别出您可能不小心隐藏了某个库,因此您可以重命名

我希望有一个更好的解决方案,例如

#include <foo>
#include "foo"
来区分标准库和本地文件,或者使用 lint 配置来检测我创建的文件何时遮盖标准库。

在我前进的过程中如何避免这个问题?

phrogz:~/proj/ai$ ls
numbers.py

phrogz:~/proj/ai$ cat numbers.py 
import pygame

phrogz:~/proj/ai$ python numbers.py
Traceback (most recent call last):
  File "/home/phrogz/proj/ai/numbers.py", line 1, in <module>
    import pygame
  File "/home/phrogz/.local/lib/python3.11/site-packages/pygame/__init__.py", line 264, in <module>
    import pygame.surfarray
  File "/home/phrogz/.local/lib/python3.11/site-packages/pygame/surfarray.py", line 47, in <module>
    import numpy
  File "/home/phrogz/.local/lib/python3.11/site-packages/numpy/__init__.py", line 130, in <module>
    from numpy.__config__ import show as show_config
  File "/home/phrogz/.local/lib/python3.11/site-packages/numpy/__config__.py", line 4, in <module>
    from numpy.core._multiarray_umath import (
  File "/home/phrogz/.local/lib/python3.11/site-packages/numpy/core/__init__.py", line 72, in <module>
    from . import numerictypes as nt
  File "/home/phrogz/.local/lib/python3.11/site-packages/numpy/core/numerictypes.py", line 595, in <module>
    _register_types()
  File "/home/phrogz/.local/lib/python3.11/site-packages/numpy/core/numerictypes.py", line 590, in _register_types
    numbers.Integral.register(integer)
    ^^^^^^^^^^^^^^^^
AttributeError: module 'numbers' has no attribute 'Integral'
python python-3.x python-import
1个回答
0
投票

出现此问题是因为运行时

python myscript.py

myscript.py
的目录会在 sys.path 前加上
。前置意味着您自己的模块是通过 import 语句在任何库模块之前
找到的。 由于这是一个“功能”(monkeypatch stdlib 的能力),因此不太可能很快改变,但 Python 3.11+ 确实提供了通过

命令行选项

环境选择退出这种潜在不安全行为的方法变量

-P

不要在

sys.path

:

 前面添加可能不安全的路径

    python -m module
  • 命令行:不要在前面添加当前工作目录。
  • python script.py
  • 命令行:不要在脚本的目录前面添加。如果是符号链接,则解析符号链接。
  • python -c code
  • python
    (REPL) 命令行:不要在前面添加空字符串,这表示当前工作目录。
    
    
另请参阅
PYTHONSAFEPATH

环境变量。 这确保了

import

仅拾取stdlib和已安装的模块,并避免无意或恶意地将本地(通常是用户可写)目录中的模块隐藏起来。

参考:

https://github.com/python/cpython/pull/31542

© www.soinside.com 2019 - 2024. All rights reserved.