从父文件夹中的模块导入函数到脚本

时间:2019-07-12 22:18:22

标签: python-3.x python-import

我知道进口是头疼的问题,但其他解决方案都对我没有帮助。

尝试从脚本的父文件夹内的模块导入函数时,出现ModuleNotFoundError错误。这是文件夹结构。

  • python_tools
    • command_line
      • cli_script.py
    • utils.py

cli_script.py:

from python_tools.utils import foo

def bar():
   foo()

if __name__ == "__main__": 
    bar()

utils.py:

def foo():
    return x

def foo2():
    return y

这在我点击“运行”时在PyCharm中有效,但是在使用python3 cli_script.py从命令行运行它时遇到上述错误。

我也尝试过python3 -m cli_script.py,这是相同的错误: ModuleNotFoundError: No module named 'python_tools'

从其他答案中我发现,这与我的sys.path有关。他们通常建议在脚本中以某种方式对其进行修改,但这似乎很hacky /非pythonic。

这个想法是要有一个带有一堆函数的模块,然后将它们以配方样式导入到一堆工具中,这些工具被隔离到不同的目录中。所有这些工具都是脚本(如果_name__ == _main __)。

请告诉我是否有更好的目录结构,或者如果没有骇人的解决方法,这是不可能的。

谢谢!

2 个答案:

答案 0 :(得分:0)

首先,一旦您pip install您的软件包,此实际上就可以使用,即使只有--editable个用于本地测试的选项也是如此。因为Python解释器将能够在模块搜索路径上找到您的软件包python_tools,然后从那里获取它。

我不知道似乎正在发生的PyCharm魔术。但是,可以,您可以将父文件夹“手动”添加到模块搜索路径。例如,像这样:

import sys
sys.path.append('..')

通常可以做到。如果相对路径..没有切掉,或者看起来太“ hacky”,您还可以从预定义的__file__属性并使用{{ 3}}或os.path中的方法(并转换为strappendsys.path)。

更好的目录结构可能是将utils.py与命令行脚本放在同一文件夹中,或者放在子文件夹中,作为软件包中的模块。这是因为脚本的目录在由解释器直接执行时始终位于模块搜索路径上。

答案 1 :(得分:0)

John的所有解决方案都能正常工作,我基本上采用了最后一个解决方案,但是想形式化我遇到的问题(现在更好地理解了)。

Python的sys.path是基于执行上下文构建的。由于我是从不同目录执行脚本,因此导入是相对于该上下文的。

我通过添加以下内容对相对导入进行硬编码来解决此问题:

import os, sys
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))

到cli_script.py的顶部。这是最便携式的解决方案。

一个更优雅的解决方案是pip install utils.py,使其始终位于sys.path上,并且可以由任何模块/脚本导入。

您也可以在bash配置文件中添加PYTHONPATH环境变量,但是我认为解决方案是世界上最差的。

Chris Yeh令人难以置信的write-up帮助我解决了这个问题,请参阅案例4。