在目录之间导入模块

时间:2017-11-20 11:54:07

标签: python python-3.x python-import

更新(显示最终代码)

由于这似乎很难解释,我分享了这个项目。对于那些提出这个问题的人,你可以在这里看到完整的项目:

https://github.com/jeffnyman/pacumen

调出对我有用的文件:

graphical_pacman

https://github.com/jeffnyman/pacumen/blob/master/displays/graphical_pacman.py

布局

https://github.com/jeffnyman/pacumen/blob/master/mechanics/layout.py

有了__init__.pysetup.py个文件,我现在可以运行如下命令:

python displays/graphical_pacman.py

python mechanics/layout.py

执行这些命令后,所有导入现在都可以正确解析。您可以看到我在每个文件中使用的所有import语句以及各种__init__.py文件的位置。

原始问题

我无法获得似乎很简单的工作:在目录之间导入模块。这一切都在Python 3中,所以如果我可以提供帮助,我不想在所有地方都有__init__.py个文件,这里的许多答案都是"对"方式。

我有这样的结构:

project
  displays
    graphical_pacman.py
  mechanics
    layout.py

layout.py文件有一个名为get_layout()的顶级函数,我想从graphical_pacman.py中调用它。

在graph_pacman.py中找到必要的最小代码我有:

import layout

if __name__ == '__main__':
  board = layout.get_layout("test_maze.lay")

在IDE中显示正常,甚至为我自动填充它。运行graphical_pacman.py可以解决这个问题:

File "displays/graphical_pacman.py", line 3, in <module>
  import layout
ModuleNotFoundError: No module named 'layout'

然后我尝试了这个:

from mechanics.layout import get_layout

if __name__ == '__main__':
  board = mechanics.layout.get_layout("test_maze.lay")

不能这样做:

File "displays/graphical_pacman.py", line 3, in <module>
  from mechanics.layout import get_layout
ModuleNotFoundError: No module named 'mechanics'

我试过了:

from mechanics import layout

if __name__ == '__main__':
  board = layout.get_layout("test_maze.lay")

我试过了:

from layout import get_layout

if __name__ == '__main__':
  board = get_layout("test_maze.lay")

不起作用。得到了这个:

File "displays/graphical_pacman.py", line 3, in <module>
  from layout import get_layout
ModuleNotFoundError: No module named 'layout'

我尝试使用相对导入(使用。之前的东西),但这也不起作用。我也尝试使用*来导入(基本上导入所有内容)。也不起作用。当我说&#34;没有工作&#34;我得到了上述错误的一些变化。

我已尝试从python graphical_pacman.py目录和根displays目录中运行命令project。每次都会出现相同的错误。

我也尝试过使用sys.path,例如sys.path.insert(0, '../mechanics')。我还根据我在这里看到的其他答案尝试了sys.path.append('../')的变体。同样,我得到的只是上述错误的变化。

我错过了什么?

2 个答案:

答案 0 :(得分:2)

第二次更新: 我已发出拉取请求,请将其检出 这就是我所做的:我从项目根目录创建了一个包,并使用pip安装它。详情如下:

添加的文件:

pacumen
    __init__.py
    setup.py
    displays
        __init__.py
    library
        __init__.py
    mechanics
         __init__.py

pacumen的内容/ __ init __。py:

from . import displays
from . import library
from . import mechanics

pacumen / setup.py的内容:

import setuptools


setuptools.setup(
    name='pacumen',
    version='0.01dev',
    packages=['displays',
                'library',    
                'mechanics',
            ],
    author='jefferyman',
    author_email='something@something.com',
    description='Pacman. Duh.',
    long_description=open('README.md').read(),        
    )

pacumen / displays的内容/ __ init __。py:

from . import graphical_helpers
from . import graphical_pacman
from . import graphical_support

pacumen / library的内容/ __ init __。py:

from . import structures
from . import utilities

pacumen / mechanics的内容/ __ init __。py:

from . import grid
from . import layout

文件更改

pacumen /力学/ layout.py:

from mechanics.grid import Grid

确保您的虚拟环境处于活动状态。 (进一步说明的说明) 最后,导航到项目根目录并将项目根目录作为包安装:

pip install --editable .  # or pip install -e .  (Note the  period at the end)

现在只要激活虚拟环境,就不应该有任何导入问题。请确保使用样式的import语句:

from mechanics.grid import Grid

虚拟环境创建和激活:

对于那些阅读,如果还没有制作虚拟环境,现在是的好时机。如果制作确保激活它。如果没有,导航到项目目录的根目录(pacumen)并运行

$ python -m venv venvdir

然后,一旦创建,运行:

<project-root>$ .venvdir\Scripts\activate  # for windows.
OR
<project-root>$ source venvdir/bin/activate  # for linux bash

更新:要检查的第一件事是没有循环导入,这意味着你要从mechanics中导入graph_pacman中的某些内容,而在graph_pacman中导入其他东西。还要确保您的模块名称不会与内置的python模块名称冲突。如果它在这些方面都很好,

  1. 你试过这个吗? from project.mechanics import layout
  2. 如果没有工作,请在项目,显示器,机械师中放置__init__.py文件。
    在project / displays / __ init__.py中添加from . import graphical_pacman 在project / mechanics / __ init__.py中添加from. import layout
  3. 如果这些都不起作用,请创建一个包,导航到包根并使用pip install -e .
  4. 将其安装在您的环境中

答案 1 :(得分:0)

我有一些有用的东西,所以我有 的答案,但完整的答案是,我所能做的就是用Python来完成,据我所知。这里的部分问题是,当我学到更多时,我意识到我的问题在我希望如何执行方面措辞不够好。

以下可以的工作方式。如果在graphical_pacman.py中,我会这样做:

if __name__ == '__main__':
  sys.path.append('../')
  from mechanics import layout

  board = layout.get_layout("test_maze.lay")

这终于有效了!

但......

我必须从python graphical_pacman.py目录而不是项目根目录运行displays。 (意思是,我无法从项目根目录执行此命令:python displays\graphical_pacman.py。)

但......

执行仍然会遇到错误:

Traceback (most recent call last):
  File "graphical_pacman.py", line 18, in <module>
   from mechanics import layout
  File "../mechanics/layout.py", line 4, in <module>
   from grid import Grid
ModuleNotFoundError: No module named 'grid'

这来自layout.py中的这一行:

from grid import Grid

如果我将该行更改为相对导入:

from .grid import Grid
python graphical_pacman.py目录运行时,

现在我的displays命令有效。

但......

现在我无法运行python layout.py,这也是必要的。那显然是因为相对导入现在在那里,所以我得到了这个错误:

Traceback (most recent call last):
  File "layout.py", line 4, in <module>
   from .grid import Grid
ModuleNotFoundError: No module named '__main__.grid'; '__main__' is not a package

我发现的问题是我有时需要单独运行文件。您会看到mechanics\layout.py有一个if __name__ == '__main__':部分。 displays\graphical_support.py也是如此。这些是必要的,所以人们可以通过直接运行这些文件来了解事情是如但最终这些文件将由编排所有内容的目录根目录中的文件使用/导入。有时文件(如布局)将取决于其他文件(如网格)。

所以似乎答案是Python不能做我想做的事情,这基本上只是寻求灵活性。

我想我可以通过将所有文件放在一个目录中来处理所有这些,这似乎是这里最好的答案,而且似乎是其他项目如何完成它。这似乎是一个糟糕的方法,但我正在权衡与进口机制的斗争,特别是因为我现在发现该机制根据执行情况以不同的方式工作。