2016-08-17 56 views
2

假设我有一个文件夹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_datasetup.py。这就是为什么cimport不需要上面例子中的绝对导入。但是,对于*.py文件(据我所知),这是不可能的,唯一的方法是使用绝对和相对导入。

回答

3

由于您添加了__init__.py文件,因此您已经制作了一个包。所以,现在,从包中导入时必须使用该包名称:

# my_algorithm.py 
import my_module.my_utils as mu 
from my_module.my_settings import My_settings 

def alg(): 
    # do something 

if __name__ == "__main__": 
    alg() 
+0

是的,这样可以解决问题,但似乎并不正确。在正式创建模块之前和之后,模块和子模块的名称空间和层次结构应该是等效的。否则,只有因为他决定创建一个模块而需要返回并修改所有“import ...”。 – Gioker

+0

@Gioker是的,好吧,他们不是。抱歉。在添加'__init__'之前,没有适当的名称空间。你还没有创建一个模块。你已经有了单独的模块。你将它们组合成一个包。 –

+0

@Gioker绝对导入是推荐的方式: https://www.python.org/dev/peps/pep-0008/#imports –