从不同子文件夹的子文件夹相对导入python模块
Posted
技术标签:
【中文标题】从不同子文件夹的子文件夹相对导入python模块【英文标题】:Relative importing python module from a subfolder from a different subfolder 【发布时间】:2013-01-18 21:36:24 【问题描述】:我正在尝试使用 alembic,它是 python 中的一个 sqlalchemy 工具。您键入一个命令,它会生成一个文件夹“alembic”,其中包含 py 文件。里面的 py 文件需要在一个名为“myapp”的单独文件夹中链接到我的应用程序。但我无法链接它。它说它不存在并且相对导入不起作用。
所以我需要从 myapp/configs/config.py 文件中导入我的配置类。
/apps
+--/alembic
|----env.py <--- the calling file
+--/myapp
|----configs/__init__.py <--- has "DefaultConfig" class imported
|----configs/config.py <--- I want to import the class inside here.
在 env.py 中:
from myapp.configs import DefaultConfig
没用。
我试过了:
from ..myapp.configs import DefaultConfig
没有成功。
alembic 文档中的示例代码说只使用“myapp.whatever”。
我什至在环境变量中将“/apps”和“/myapp”添加到 PYTHON_PATH。
示例错误:
File "D:\apps\myapp\lib\site-packages\alembic\command.p
y", line 97, in revision
script.run_env()
File "D:\apps\myapp\lib\site-packages\alembic\script.py
", line 191, in run_env
util.load_python_file(self.dir, 'env.py')
File "D:\apps\myapp\lib\site-packages\alembic\util.py",
line 186, in load_python_file
module = imp.load_source(module_id, path, open(path, 'rb'))
File "alembic\env.py", line 5, in <module>
from ..myapp.configs import DefaultConfig as conf
ValueError: Attempted relative import in non-package
【问题讨论】:
我很困惑,您是否为该项目运行了 setup.py? 在我 pip install alembic... 我做了“alembic init alembic”并生成了文件。 尝试在导入前将'../myapp'
附加到 env.py 中 Python 的 sys.path
。
【参考方案1】:
您的问题有两种可能的解决方案:
修改你的 PYTHONPATH 环境变量
通过在终端中运行以下 BASH / SH shell 命令来添加应用目录的路径:
$ export PYTHONPATH=$PYTHONPATH:'/path/to/apps'
请不要将其添加到 PATH 环境变量中不起作用。要了解有关 PYTHONPATH 的更多信息、如何管理它以及关于模块的友好友好信息:
http://www.stereoplex.com/blog/understanding-imports-and-pythonpath
但是请注意,这种方法确实会影响您系统的 PYTHONPATH。强烈建议使用 virtualenv - 以防万一出现问题,它不会影响您的所有系统和其他应用程序。使用 virtualenvwrapper 时:
$ add2virtualenv '/path/to/apps'
更多HERE.
在 Python 脚本中添加路径
或者,您也可以这样做,但只针对脚本运行时添加:
import sys
sys.path.append('/path/to/apps')
到您的apps/alembic/env.py
文件。
最后,在同一个文件中,进行如下修改:
from myapp.configs.config import DefaultConfig
请注意,您的 apps/myapp
文件夹还应包含 __init__.py
文件(可能为空),以使 Python 将其视为 Demian Brecht 指出的模块。
【讨论】:
为我工作!默认情况下,alembic 文件夹是否应该在应用程序模块内?这似乎是一种奇怪的行为。另外,为了避免这条艰难的道路import sys,os sys.path.append(os.getcwd())
【参考方案2】:
myapp
是一个独立的应用程序,还是一个子应用程序,例如您可以使用 Django 找到的应用程序?如果它是一个独立的应用程序,那么你有点做错了。您真正想要做的是安装您的应用程序具有的依赖项,以便能够访问它们而不必使用相对导入等(这是不好的做法,尤其是如果除了你之外的任何人正在使用该应用程序)。
您可能想要做的事情(同样,如果它是独立的):
为您的应用程序设置一个虚拟环境(我强烈推荐使用 virtualenvwrapper,我刚刚在我的闪亮的新(和不完整的)博客中写过它:http://demianbrecht.github.com/posts/2013/01/02/virtualenvwrapper/ 将alembic
安装为依赖项:pip install alembic
创建requirements.txt
文件:pip freeze > requirements.txt
现在,您应该可以在项目中的任何位置通过 import alembic
使用 alembic。
编辑:
您的目录结构也有点不稳定。您需要将所有特定于应用程序的模块放入另一个 myapp
子目录:
myapp
myapp
__init__.py
configs/__init__.py
这样做的原因是您可以将myapp
添加到您的PYTHONPATH
并能够通过from myapp import foo
从您的应用程序中导入任何模块。就目前而言,如果myapp
在您的PYTHONPATH
上,您将只能从第二个命名空间级别(即import configs
)访问子模块,这显然是不好的。
【讨论】:
这是一个 Flask 应用程序。好吧,我不确定如何让 alembic 找到我的配置文件并从中获取 DB SQL URI。该示例说只做“app.config [”SQLALCHEMY_URI“]或其他东西,但它没有定义如何获取“app”。抛出的错误是在我运行'alembic revision --autogenerate -m“test”之后' 这样我就可以创建我的初始模型了。 只要在请求上下文中,您就可以使用from flask get current_app
获取app
。
好吧,你只会在网站甚至离线时执行命令时使用 alembic,所以它必须是应用程序上下文。我想我需要一些新代码,比如 flask-alembic以上是关于从不同子文件夹的子文件夹相对导入python模块的主要内容,如果未能解决你的问题,请参考以下文章