假设我有一个文件夹Awesome_stuff/my_module
,它包含以下文件:my_algorithm.py
,my_settings.py
,my_utils.py
。 主文件my_algorithm.py
包含以下行:使子模块在同一Python模块内彼此可见
# my_algorithm.py
import my_utils as mu
from my_settings import My_settings
def alg():
# do something
if __name__ == "__main__":
alg()
运行python my_algorithm.py
不会产生任何问题。然而,如果我想在我的Python库中安装这个模块,事情就会改变。为了做到这一点,我添加一个空__init__.py
文件my_module
文件夹中的my_module
文件夹内,外,我把一个setup.py
文件看起来像这样:
from setuptools import setup
setup(
name = 'Awesome_stuff',
version = '1.0.0',
packages = ['my_module'],
# # dependencies
install_requires = ['numpy','scipy', 'numpydoc>=0.5', 'pyomo>=4.3.11388', 'mock>=1.1.3'],
# # project metadata
author = 'Me',
author_email = '[email protected]',
description = 'This module contains awesome stuff',
license = 'BSD',
url = 'http://my_website.com',
download_url = 'my_download_address.com'
)
运行python setup.py install
产生卵子和模块安装在我的Python图书馆。现在主要的文件夹Awesome_stuff
包含:
Awesome_stuff.egg-info
build (folder created during installation)
dist (folder created during installation)
my_module (my original folder plus __init__.py)
setup.py
为了执行一些等同于原来的python my_algorithm.py
我现在可以创建包含有类似from my_module.my_algorithm import *
一个新的Python文件test.py
,然后执行alg()
。
不幸的是,线from my_module.my_algorithm import *
生成以下错误:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "build/bdist.macosx-10.11-intel/egg/my_module/my_algorithm.py", line 25, in <module>
ImportError: No module named my_utils
我怎样才能解决这个问题,而无需修改原来的三个模块的文件?我看不出这里出了什么问题。
此外,import my_module
不会产生任何错误。我在这里有点困惑。 当模块是独立文件夹时,为什么从同一文件夹导入子模块并在Python库中安装时无法工作?
更一般的问题:导入/使用可能相互依赖的子模块的正确/建议的方式是什么?文件__init__.py
可能在这种情况下起作用吗?
感谢。
OS X埃尔队长,Python的2.7.10
EDIT
作为一个例子,我看着Python库Zen,其以类似的方式构造:
Zen
build
zen
folder1
folder2
...
__init__.py
graph.pxd
graph.pyx
digraph.pxd
digraph.pyx
...
Makefile
setup.py
在这种情况下,digraph.pyx
(即覆盖一些graph.pxd
声明)包含行from graph cimport *
,这当然不会导致任何问题。请注意,它不会说:from zen.graph cimport *
。
最后的编辑
当使用cimport
你可以以设置*.pxd
文件的路径定义package_data
内setup.py
。这就是为什么cimport
不需要上面例子中的绝对导入。但是,对于*.py
文件(据我所知),这是不可能的,唯一的方法是使用绝对和相对导入。
是的,这样可以解决问题,但似乎并不正确。在正式创建模块之前和之后,模块和子模块的名称空间和层次结构应该是等效的。否则,只有因为他决定创建一个模块而需要返回并修改所有“import ...”。 – Gioker
@Gioker是的,好吧,他们不是。抱歉。在添加'__init__'之前,没有适当的名称空间。你还没有创建一个模块。你已经有了单独的模块。你将它们组合成一个包。 –
@Gioker绝对导入是推荐的方式: https://www.python.org/dev/peps/pep-0008/#imports –