我有以下文件夹结构:
app
__init__.py
utils
__init__.py
transform.py
products
__init__.py
fish.py
在fish.py中,我导入transform
,如下所示:import utils.transform
当我从Pycharm运行fish.py时,它工作得非常好。然而,当我从终端运行fish.py时,我得到了错误ModuleNotFoundError: No module named 'utils'
我在终端中使用的命令:来自应用程序文件夹python products/fish.py
我已经研究了这里建议的解决方案:Importing files from different folder,将应用程序文件夹的路径添加到sys.path
帮助中。但是,我想知道是否有其他方法可以让它在不向^{
我查看了一些开源项目,看到了许多从并行文件夹导入模块而不向sys.path添加任何内容的示例,例如: https://github.com/jakubroztocil/httpie/blob/master/httpie/plugins/builtin.py#L5
如何让它以同样的方式为我的项目工作
这扩展了“疯狂物理学家”的答案
首先,假设
app
本身是一个包(因为您向它添加了__init__.py
),并且utils
和products
是它的子包,您应该将导入更改为import app.utils.transform
,并从根目录运行Python(其父目录)。这个答案的其余部分假设您已经这样做了。(如果您不打算将app
作为根包,请在评论中告诉我。)问题是,您正在运行
app.products.fish
,就像它是一个脚本一样,即通过将文件的完整路径提供给python
命令:这使Python认为这个
fish.py
文件是一个独立的脚本,不属于任何包。正如文档中所定义的(参见here,在<script>
下),这意味着Python将在与脚本相同的目录中搜索模块,即app/products/
:但是当然,
app
文件夹不在app/products/
中,因此如果您尝试导入app
或任何子包(例如app.utils
),它将抛出一个错误启动作为包一部分的脚本的正确方法是使用
-m
(模块)开关(reference),该开关将模块路径作为参数,并将该模块作为脚本执行(但将当前工作目录保留为模块搜索路径):因此,您应该使用以下方法启动您的程序:
现在,当
app.products.fish
尝试导入app.utils.transform
模块时,它将在当前工作目录(其中包含app/...
树)中搜索app
并成功个人建议:不要将可运行脚本放入包中。仅使用包来存储所有逻辑和功能(函数、类、常量等),并编写一个单独的脚本来运行应用程序(如您所愿),将其置于包之外。这将使您免于此类问题(包括the double import trap),并且还有一个优点,即您可以为同一个包编写多个运行配置,只需为每个包编写一个单独的启动脚本
您可能想要运行
python -m products.fish
。它与python products/fish.py
之间的区别在于前者大致相当于在shell中执行import products.fish
(但是__name__
设置为__main__
),而后者不知道它在包层次结构中的位置相关问题 更多 >
编程相关推荐