将函数从位于父文件夹中的模块导入脚本
Importing functions from a module located in parent folder to script
我知道导入是一个常见的头痛问题,但 none 其他解决方案对我有用。
我在尝试从脚本的父文件夹中的模块导入函数时收到 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
当我点击 'Run' 时,这在 PyCharm 中有效,但是当 运行 从命令行使用 python3 cli_script.py
时,我得到了上述错误。
我也试过 python3 -m cli_script.py
这是同样的错误:
ModuleNotFoundError: No module named 'python_tools'
从其他回答中我了解到这与我的sys.path
有关。他们大多建议在脚本中以某种方式修改它,但这似乎很老套/非 pythonic。
我们的想法是拥有一个带有一堆函数的模块,然后将这些函数以配方样式导入到一堆工具中,这些工具被隔离到不同的目录中。所有这些工具都将是脚本(如果 _name__ == _main__)。
请告诉我是否有更好的目录结构,或者如果没有 hacky 变通办法就无法实现。
谢谢!
首先,一旦您 pip install
您的包,这个 将 实际上工作,即使只有用于本地测试的 --editable
选项。因为 Python 解释器将能够在模块搜索路径上找到您的包 python_tools
并从那里获取它。
我不知道似乎正在发生的 PyCharm 魔法。但是,是的,您可以将父文件夹 "manually" 添加到模块搜索路径。例如像这样:
import sys
sys.path.append('..')
通常这样就可以了。如果相对路径 ..
没有削减它,或者看起来太 "hacky",您还可以从 pre-defined __file__
属性获取脚本的绝对路径并使用来自 os.path
or methods from pathlib
的函数(并转换为 str
以便 append
到 sys.path
)。
更好的目录结构可能是将 utils.py
放在与命令行脚本相同的文件夹中,或者放在子文件夹中,作为包中的模块。那是因为解释器直接执行的脚本目录总是在模块搜索路径上。
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
并且可以被任何 module/script.
导入
您还可以将 PYTHONPATH 环境变量添加到您的 bash 配置文件中,但我认为该解决方案是最糟糕的。
Chris Yeh 令人难以置信的 write-up 帮助我解决了这个问题,请参阅案例 #4。
我知道导入是一个常见的头痛问题,但 none 其他解决方案对我有用。
我在尝试从脚本的父文件夹中的模块导入函数时收到 ModuleNotFoundError。这是文件夹结构。
- python_tools
- command_line
- cli_script.py
- utils.py
- command_line
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
当我点击 'Run' 时,这在 PyCharm 中有效,但是当 运行 从命令行使用 python3 cli_script.py
时,我得到了上述错误。
我也试过 python3 -m cli_script.py
这是同样的错误:
ModuleNotFoundError: No module named 'python_tools'
从其他回答中我了解到这与我的sys.path
有关。他们大多建议在脚本中以某种方式修改它,但这似乎很老套/非 pythonic。
我们的想法是拥有一个带有一堆函数的模块,然后将这些函数以配方样式导入到一堆工具中,这些工具被隔离到不同的目录中。所有这些工具都将是脚本(如果 _name__ == _main__)。
请告诉我是否有更好的目录结构,或者如果没有 hacky 变通办法就无法实现。
谢谢!
首先,一旦您 pip install
您的包,这个 将 实际上工作,即使只有用于本地测试的 --editable
选项。因为 Python 解释器将能够在模块搜索路径上找到您的包 python_tools
并从那里获取它。
我不知道似乎正在发生的 PyCharm 魔法。但是,是的,您可以将父文件夹 "manually" 添加到模块搜索路径。例如像这样:
import sys
sys.path.append('..')
通常这样就可以了。如果相对路径 ..
没有削减它,或者看起来太 "hacky",您还可以从 pre-defined __file__
属性获取脚本的绝对路径并使用来自 os.path
or methods from pathlib
的函数(并转换为 str
以便 append
到 sys.path
)。
更好的目录结构可能是将 utils.py
放在与命令行脚本相同的文件夹中,或者放在子文件夹中,作为包中的模块。那是因为解释器直接执行的脚本目录总是在模块搜索路径上。
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
并且可以被任何 module/script.
您还可以将 PYTHONPATH 环境变量添加到您的 bash 配置文件中,但我认为该解决方案是最糟糕的。
Chris Yeh 令人难以置信的 write-up 帮助我解决了这个问题,请参阅案例 #4。