如何将Python源代码分割成单独的目录?
以下是我公司 "foo.com" 使用的一些不同的 Python 包:
com.foo.bar.web
com.foo.bar.lib
com.foo.zig.web
com.foo.zig.lib
com.foo.zig.lib.lib1
com.foo.zig.lib.lib2
这是传统的将源代码存储在磁盘上的方法:
pysrc/
com/
foo/
bar/
web/
lib/
zig/
web/
lib/
lib1/
lib2/
PYTHONPATH=pysrc
但是为了更好地组织(不同的团队、不同的版本控制等等),我们想要这样存储:
bar/
pysrc/
com/
foo/
bar/
web/
lib/
zig/
pysrc/
com/
foo/
zig/
web/
lib/
lib1/
lib2/
PYTHONPATH=bar/pysrc:zig/pysrc
问题是:
这种第二种组织方式有没有什么问题呢?
比如说,如果我们使用 import com.foo
,Python 会在哪里寻找 __init__.py
文件呢?
把这些目录做成符号链接(symlink)合理吗?例如:
pysrc/
com/
foo/
bar/ -> symlink to /bar/pysrc/com/foo/
zig/ -> symlink to /zig/pysrc/com/foo/
欢迎任何关于代码组织的一般建议。
2 个回答
3
在阅读PEP 420 页面时,发现你可以在共享包中添加以下的 __init__.py
文件:
from pkgutil import extend_path
__path__ = extend_path(__path__, __name__)
所以你的目录结构应该是这样的(带 * 标记的 __init__.py
文件包含上面的代码):
myroot/
├── bar
│ └── pysrc
│ └── com
│ ├── ****__init__.py****
│ └── foo
│ ├── ****__init__.py****
│ └── bar
│ ├── __init__.py
│ ├── lib
│ │ ├── __init__.py
│ │ └── barlib.py
│ └── web
│ ├── __init__.py
│ ├── barweb.py
└── zig
└── pysrc
└── com
├── ****__init__.py****
└── foo
├── ****__init__.py****
└── zig
├── __init__.py
├── lib
│ ├── __init__.py
│ ├── lib1
│ │ ├── __init__.py
│ │ └── ziblib1.py
│ └── lib2
│ ├── __init__.py
│ └── ziblib2.py
└── web
├── __init__.py
├── zigweb.py
设置 Python 路径指向你的 com/
目录:
barPath=/myroot/bar/pysrc/
zigPath=/myroot/zig/pysrc/
export PYTHONPATH=$PYTHONPATH:$barPath:$zigPath
为了测试(我在 2.7.14 和 3.6.4 上尝试过):
from com.foo.bar.web.barweb import BarWeb
from com.foo.zig.web.zigweb import ZigWeb
b = BarWeb()
z = ZigWeb()
如果没有 __init__.py
的代码,会得到:
ImportError: No module named zig.web.zigweb
4
Python会按照顺序检查sys.path中的路径(这其中包括PYTHONPATH和其他一些路径),寻找com.foo这个包。它会使用找到的第一个包,而不会考虑其他的包。这和Perl或Java不同,后者会把多个包的命名空间合并在一起。虽然你可以对__path__
做一些操作来改变这种行为,但默认情况下,Python的规则是“先找到的优先”。
只要你把com.foo.bar的所有内容放在bar/文件夹里,把com.foo.zig的所有内容放在zig/文件夹里,第二种布局就不会有问题。