python - 从 __init__ 中的 Python 子模块导入方法,但不是子模块本身
问题描述
我有一个具有以下结构的 Python 模块:
mymod/
__init__.py
tools.py
# __init__.py
from .tools import foo
# tools.py
def foo():
return 42
现在,当 时import mymod
,我看到它有以下成员:
mymod.foo()
mymod.tools.foo()
我不想要后者;它只会污染命名空间。
有趣的是,如果tools.py
被调用foo.py
,你会得到你想要的:
mymod.foo()
(显然,这仅在每个文件只有一个函数时才有效。)
如何避免导入tools
?请注意,投入foo()
不是__init__.py
一种选择。(实际上,有许多类似的函数foo
绝对会使文件变得混乱。)
解决方案
The existence of the mymod.tools
attribute is crucial to maintaining proper function of the import system. One of the normal invariants of Python imports is that if a module x.y
is registered in sys.modules
, then the x
module has a y
attribute referring to the x.y
module. Otherwise, things like
import x.y
x.y.y_function()
break, and depending on the Python version, even
from x import y
can break. Even if you don't think you're doing any of the things that would break, other tools and modules rely on these invariants, and trying to remove the attribute causes a slew of compatibility problems that are nowhere near worth it.
Trying to make tools
not show up in your mymod
module's namespace is kind of like trying to not make "private" (leading-underscore) attributes show up in your objects' namespaces. It's not how Python is designed to work, and trying to force it to work that way causes more problems than it solves.
The leading-underscore convention isn't just for instance variables. You could mark your tools
module with a leading underscore, renaming it to _tools
. This would prevent it from getting picked up by from mymod import *
imports (unless you explicitly put it in an __all__
list), and it'd change how IDEs and linters treat attempts to access it directly.
推荐阅读
- graph - TraMineR 图上的图边距太大
- django - 为什么在 Django for Heroku 中的 Debug=False 时出现服务器 (500) 错误?
- python - 将 csv 文件值与均方误差进行比较
- laravel - 在 laravel 中使用中间件判断页面访问量
- python - 如何修复我的工作日,以在周六和周日输出特定信息。从周一到周五,人们都在工作,周六到周日是周末
- java - 尝试模拟多个 Java 接口时出现问题
- verilog - 是否有可综合的任务或端口接口方式来更好地将 AXI 信号分配给本地模块?
- python - 错误:尝试在 python 中解决 ODE 时出现“标识符中的无效字符”
- angular - 如何在输入类型搜索中检测到单击取消“x”?
- codenameone - 工具栏上的 sideMenuAnimSpeedInt 是否可用?