将单个python .py文件拆分为多个相互依赖的文件
我想把我写的一个大Python模块拆分成多个文件,每个文件里放一个函数,这些函数之间可能有依赖关系。下面是我想到的一个简单例子:
首先,这是一个独立的.py模块:
#[/pie.py]
def getpi():
return pi()
def pi():
return 3.1416
显然,当我导入并调用这两个函数时,它们都能正常工作。现在我把它们拆分到不同的文件里,并加了一个init.py文件来把它们整合起来:
#[/pie/__init__.py]
from getpi import *
from pi import *
__all__=['getpi','pi']
#[/pie/getpi.py]
def getpi():
return pi()
#[/pie/pi.py]
def pi():
return 3.1416
因为getpi()函数依赖于pi()函数,所以按照现在的结构调用它会出现错误:
>>> import pie
>>> pie.getpi()
Traceback (most recent call last):
File "<pyshell#7>", line 1, in <module>
pie.getpi()
File "C:\python\pie\getpi.py", line 2, in getpi
return pi()
NameError: global name 'pi' is not defined
为了解决这个问题,我现在的做法是这样写init.py:
#[/pie/__init__.py]
import os as _os
__all__ = []
for _f in _os.listdir(__path__[0]):
if not _f == '__init__.py' and _f.endswith('.py'):
execfile('%s\\%s'%(__path__[0],_f))
__all__.append(_os.path.splitext(_f)[0])
这样就可以正常工作了:
>>> import pie
>>> pie.getpi()
3.1416
现在一切都像是在一个单独的.py文件中一样工作。init.py可以包含所有各个函数需要的高级导入(比如numpy、os、sys、glob等)。
我觉得这样组织模块是“对的”。新的函数在下次导入时会自动加载(不需要每次都在init.py里添加)。我可以通过查看目录里的内容,快速了解哪些函数是可以使用的,而且所有东西都按字母顺序整理得很好。
目前我看到的唯一缺点是,只有init.py会被编译成字节码,而其他的.py文件不会。不过加载速度并没有问题,所以我不在乎。此外,我也意识到这可能会在打包时出现问题,但我也不太在意,因为我们的脚本是通过自己的版本控制系统分发的。
这样组织Python模块可以吗?如果不行,那正确的做法是什么呢?
1 个回答
4
“正确”的做法是把需要用到的模块导入到相应的位置:
# pi.py
def pi(): return 3.1417
# getpi.py
from .pi import pi
def getpi(): return pi()
# __init__.py
from .pi import *
from .getpi import *
确保你没有循环依赖。循环依赖是指两个或多个模块互相依赖,这种情况在任何情况下都是不好的。你可以通过将代码抽象到合适的层级来避免这种问题。