Python: 如何确保您的代码不会被您使用的库意外导入?
Python: how to ensure your code won't be accidentally imported by the libraries you use?
几个小时前,我粗心大意,将我的短剧本命名为code.py
。显然,有 such a package 被使用,例如通过 ptvsd
或 pdb
。这导致我的 code.py
被导入,并在尝试调试我的代码时导致一堆嵌套的未处理异常,缺少导入。更令人沮丧的是,回溯没有显示任何导入我的 code.py
文件的迹象,所以我花了很长时间才找到问题的根源。
我想避免将来出现这种情况,所以我的问题是:确保您使用的模块不会因此类名称冲突而错误地导入您的代码的最佳做法是什么?
在开始导入其他模块之前,您可以在主模块的开头修改 sys.path
:
import sys
sys.path.append(sys.path.pop(0))
以便将主模块的起始目录放在模块搜索路径的最后而不是前面,以便其他同名模块优先。
编辑:对于所有反对者,这个答案确实有效。
例如运行 code.py
内容如下:
import pdb
pdb.run('print("Hello world")')
会提高:
AttributeError: module 'pdb' has no attribute 'run'
因为code.py
没有定义run
,而运行 code.py
有以下内容代替:
import sys
sys.path.append(sys.path.pop(0))
import pdb
pdb.run('print("Hello world")')
将正确执行 pdb.run
:
> <string>(1)<module>()
(Pdb)
你无法完全避免,有人能够错误地导入你的模块。
您可以在名称从 "well known" 到 "less known" 的子包中更好地构建代码。例如。如果您正在为某家公司开发代码,那么您可能需要这样的结构:
company.country.location.department.function
如果您的代码被更多人接受和使用,您可以将代码放入上层命名空间,以便在 company.country.location.department.function
中可用
和 company.country.location.department
这是一个常见的陷阱,实际上没有避免它的万无一失的方法。至少你可以确保你的模块都存在于包中(如果这是一个没有可重用代码的小项目,至少有一个包)这样你就可以将它们用作 from mypackage import code
而不是 import code
(也使确保你使用绝对导入等),并且你总是 运行 你的代码来自包含包的目录,而不是来自包目录本身(python 首先插入当前工作目录sys.path
).
的位置
这不会阻止所有可能的名称屏蔽问题,但它应该将它们最小化。现在根据经验,一旦您至少遇到过一次此类问题,您通常会很快发现症状 - 最常见且非常明显的是一些完全不相关的 stlib 或第三方模块开始因 ImportErrors 或 AttributeErrors(与"module X has no attribute Y" 条消息)。在这一点上,如果你只是在你自己的代码中添加了一个新模块,很可能是新模块破坏了一切,所以你可以重命名它(确保你清理了 .pyo/.pyc 文件,如果有的话),看看是否它解决了这个问题。否则检查回溯以找出哪些导入失败,大多数时候你会发现你在当前工作目录中有一个同名的模块或包。
几个小时前,我粗心大意,将我的短剧本命名为code.py
。显然,有 such a package 被使用,例如通过 ptvsd
或 pdb
。这导致我的 code.py
被导入,并在尝试调试我的代码时导致一堆嵌套的未处理异常,缺少导入。更令人沮丧的是,回溯没有显示任何导入我的 code.py
文件的迹象,所以我花了很长时间才找到问题的根源。
我想避免将来出现这种情况,所以我的问题是:确保您使用的模块不会因此类名称冲突而错误地导入您的代码的最佳做法是什么?
在开始导入其他模块之前,您可以在主模块的开头修改 sys.path
:
import sys
sys.path.append(sys.path.pop(0))
以便将主模块的起始目录放在模块搜索路径的最后而不是前面,以便其他同名模块优先。
编辑:对于所有反对者,这个答案确实有效。
例如运行 code.py
内容如下:
import pdb
pdb.run('print("Hello world")')
会提高:
AttributeError: module 'pdb' has no attribute 'run'
因为code.py
没有定义run
,而运行 code.py
有以下内容代替:
import sys
sys.path.append(sys.path.pop(0))
import pdb
pdb.run('print("Hello world")')
将正确执行 pdb.run
:
> <string>(1)<module>()
(Pdb)
你无法完全避免,有人能够错误地导入你的模块。
您可以在名称从 "well known" 到 "less known" 的子包中更好地构建代码。例如。如果您正在为某家公司开发代码,那么您可能需要这样的结构:
company.country.location.department.function
如果您的代码被更多人接受和使用,您可以将代码放入上层命名空间,以便在 company.country.location.department.function
中可用
和 company.country.location.department
这是一个常见的陷阱,实际上没有避免它的万无一失的方法。至少你可以确保你的模块都存在于包中(如果这是一个没有可重用代码的小项目,至少有一个包)这样你就可以将它们用作 from mypackage import code
而不是 import code
(也使确保你使用绝对导入等),并且你总是 运行 你的代码来自包含包的目录,而不是来自包目录本身(python 首先插入当前工作目录sys.path
).
这不会阻止所有可能的名称屏蔽问题,但它应该将它们最小化。现在根据经验,一旦您至少遇到过一次此类问题,您通常会很快发现症状 - 最常见且非常明显的是一些完全不相关的 stlib 或第三方模块开始因 ImportErrors 或 AttributeErrors(与"module X has no attribute Y" 条消息)。在这一点上,如果你只是在你自己的代码中添加了一个新模块,很可能是新模块破坏了一切,所以你可以重命名它(确保你清理了 .pyo/.pyc 文件,如果有的话),看看是否它解决了这个问题。否则检查回溯以找出哪些导入失败,大多数时候你会发现你在当前工作目录中有一个同名的模块或包。