具有相同名称的Python模块(即,在包中重用标准模块名称)

BFT*_*FTM 16 python namespaces module package

假设我有一个包含模块的包:

SWS/
  __init.py__
  foo.py
  bar.py
  time.py
Run Code Online (Sandbox Code Playgroud)

并且模块需要引用彼此包含的功能.似乎我遇到了time.py模块问题,因为有一个标准模块同名.

例如,在我的foo.py模块需要我SWS.time和标准python time 模块的情况下,我遇到麻烦,因为解释器将查看包内部并time.py在它遇到标准time模块之前找到我的模块.

有没有办法解决?这是禁止的情况,模块名称是否应该重复使用?

关于包装哲学的任何解决方案和意见在这里都很有用.

Bak*_*riu 16

重用标准函数/类/模块/包的名称绝不是一个好主意.尽量避免使用它.但是,您的情况有一些干净的解决方法.

您看到的行为,导入SWS.time而不是stdlib time,是由于import古代python版本(2.x)的语义.要修复它,请添加:

from __future__ import absolute_import
Run Code Online (Sandbox Code Playgroud)

在文件的最顶部.这将改变importpython3.x 的语义,这更加明智.在这种情况下声明:

import time
Run Code Online (Sandbox Code Playgroud)

仅涉及顶级模块.因此,解释器在包内执行导入时不会考虑您的SWS.time模块,但它只使用标准库.

如果一个模块内的软件包需要输入SWS.time你的选择:

所以,你foo.py会是这样的:

from __future__ import absolute_import

import time

from . import time as SWS_time
Run Code Online (Sandbox Code Playgroud)

  • 我认为,当模块名称存在于命名空间*(如包)时,这不是一个坏主意.这是PEP328的精神.请参阅下面的答案. (3认同)

Ooz*_*ter 8

这取决于您使用的Python版本.如果你的目标Python版本是2.4或更早(2015年,我肯定不希望),那么是的,这将是不好的做法,因为没有办法(没有黑客)来区分这两个模块.

但是,在Python 2.5+中,我认为在包命名空间中重用标准的lib模块名称是完全正确的; 事实上,这就是PEP328的精神.

随着Python库的扩展,越来越多的现有包内部模块突然意外地影响了标准库模块.这是包内部特别困难的问题,因为没有办法指定哪个模块是什么意思.为了解决这种歧义,建议foo始终是可以从sys.path访问的模块或包.这称为绝对导入.

python-dev社区选择绝对导入作为默认导入,因为它们是更常见的用例,并且因为绝对导入可以提供相对(包内)导入的所有功能 - 尽管在重命名包装件时需要付出高昂代价在层次结构中或在一个包中移动另一个包时.

因为这代表了语义的变化,所以绝对导入在Python 2.5和2.6中通过使用是可选的 from __future__ import absolute_import

SWS.time显然不是time和代码的读者一样,我希望SWS.time不仅可以使用time,而且可以通过某种方式扩展它.

所以,如果SWS.foo需要导入SWS.time,那么它应该使用绝对路径:

# in SWS.foo

# I would suggest renaming *within*
# modules that use SWS.time so that
# readers of your code aren't confused
# with which time module you're using
from SWS import time as sws_time
Run Code Online (Sandbox Code Playgroud)

或者,它应该使用明确的相对导入,如Bakuriu的答案:

# in SWS.foo

from . import time as sws_time
Run Code Online (Sandbox Code Playgroud)

如果您需要在time模块中导入标准lib 模块SWS.time,首先需要导入未来的功能(仅适用于Python 2.5+;默认情况下Python 3+执行此操作):

# inside of SWS.time
from __future__ import absolute_import

import time

time.sleep(28800)  # time for bed
Run Code Online (Sandbox Code Playgroud)

注: from __future__ import absolute_imports只会影响import语句,未来的功能导入模块,将不会影响任何其他模块(如如果另一个模块依赖于相对导入,这将是有害的).


Dav*_*ain 5

正如其他人所说,这通常是一个坏主意.

话虽如此,如果您正在寻找潜在的解决方法,或者更好地了解问题,我建议您阅读以下SO问题: