从不同目录导入python模块

从不同目录导入python模块,python,python-3.x,python-import,importerror,Python,Python 3.x,Python Import,Importerror,我有一个flask应用程序,基本上具有以下结构: app/ __init__.py myapp.py common/ tool1.py tool2.py web/ __init__.py views.py api/ api_impl.py worker/ __init__.py worker.py tasks.py 我在myapp.py中初始化了我在多个地方使用的一个重要对象,我可以从common/

我有一个flask应用程序,基本上具有以下结构:

app/
  __init__.py
  myapp.py
  common/
    tool1.py
    tool2.py
  web/
    __init__.py
    views.py
    api/
      api_impl.py
  worker/
    __init__.py
    worker.py
    tasks.py
我在
myapp.py
中初始化了我在多个地方使用的一个重要对象,我可以从
common/tool1.py
web/api/api_impl.py
使用myapp导入对象的
访问它。我已经能够在
web/
myapp.py中的多个位置使用
tool1
tool2
从common.tool1导入工具1_def
导入

其他相关事实在
myapp.py
中,蓝图有一个
import-web
语句,
app/\uuuuuuuuuuuuuuuuuuuuuuupy
worker/\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
web/_init__.py
包含路线的蓝图定义

我可以使用gunicorn运行应用程序,没有任何问题,但是当我尝试使用
python app/worker/worker.py运行我的worker时,我得到了错误
modulenofounderror:no module name'myapp'
worker.py
正在尝试导入在
myapp.py
中定义的相同对象


我只是不明白为什么我可以运行这个应用程序,它可以工作,但当我试图运行工人它没有!在这种情况下,我肯定没有完全理解导入系统,我在网上读到的所有内容似乎都没有完全阐明这一点。

您的工作导入意味着项目根目录就是应用程序文件夹。因此,您需要从该文件夹(或将其添加到PYTHONPATH环境变量)中为工作人员提供午餐


此外,应删除应用程序文件夹中的
\uuuu init\uuuuuuuuupy
,因为应用程序不是包而是项目根目录。

工作导入意味着项目根目录就是应用程序文件夹。因此,您需要从该文件夹(或将其添加到PYTHONPATH环境变量)中为工作人员提供午餐


此外,应删除应用程序文件夹中的
\uuuuuuu init\uuuuuuuuuuy.py
,因为应用程序不是一个包,而是一个项目根。

我们经常用于开发和调试(但也适用于生产)的一种方法如下。您可以将其添加到每个(有问题的?)模块或所有模块(如果您选择)

import os
import sys

# Add your project root to sys.path.
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.realpath(__file__))))

from common import tool1
from common import tool2
from worker import worker
etc ...
在这里,您正在将项目根目录添加到
sys.path
。在执行导入时,Python首先查看要导入的模块的
sys.path
。因此,在这里,您将添加项目根作为
sys.path
中的第一项


另一个优点是这些导入对您的项目是明确的。例如,如果您有一个要导入的本地
工作者
模块,但在
站点包
中也有一个
工作者
包,这将首先查看您的本地项目。

我们经常用于开发和调试的一种方法(但也适用于生产环境)如下。您可以将其添加到每个(有问题的?)模块或所有模块(如果您选择)

import os
import sys

# Add your project root to sys.path.
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.realpath(__file__))))

from common import tool1
from common import tool2
from worker import worker
etc ...
在这里,您正在将项目根目录添加到
sys.path
。在执行导入时,Python首先查看要导入的模块的
sys.path
。因此,在这里,您将添加项目根作为
sys.path
中的第一项


另一个优点是这些导入对您的项目是明确的。例如,如果您有一个要导入的本地
工作者
模块,但在
站点包
中也有一个
工作者
包,这将首先查看您的本地项目。

谢谢。我删除了init.py,它没有改变任何东西,我怀疑这是好的。setup.py位于app的父文件夹中,但它确实表示包是app.web和app.worker(现在我删除了init.py)。工作程序使用应用程序文件夹中的
python-m worker.worker
成功运行,但未使用
python worker/worker.py
成功运行。知道为什么吗?有一件事,当我运行setup.py时,从app文件夹中删除
\uuuu init\uuuu.py
后,它再也找不到我的任何软件包了。我应该将setup.py移到应用程序文件夹中还是手动定义它们?您需要确定项目结构。如果你想让应用程序成为一个包,这很好,但是所有的导入都应该是这样的:import app.worker.worker还有其他更高级的方法,比如相对导入,但是根据我的经验,从根包向下导入是最好的做法。谢谢。我删除了init.py,它没有改变任何东西,我怀疑这是好的。setup.py位于app的父文件夹中,但它确实表示包是app.web和app.worker(现在我删除了init.py)。工作程序使用应用程序文件夹中的
python-m worker.worker
成功运行,但未使用
python worker/worker.py
成功运行。知道为什么吗?有一件事,当我运行setup.py时,从app文件夹中删除
\uuuu init\uuuu.py
后,它再也找不到我的任何软件包了。我应该将setup.py移到应用程序文件夹中还是手动定义它们?您需要确定项目结构。如果您希望应用程序成为一个包,那么这很好,但是所有导入都应该是这样的:import app.worker.worker还有其他更高级的方法,比如相对导入,但根据我的经验,从根包向下导入是最佳做法。
import os
import sys

# Add your project root to sys.path.
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.realpath(__file__))))

from common import tool1
from common import tool2
from worker import worker
etc ...