如何构建一个包含三个应用的Python项目并使用公共模块
我的项目里有三个Python应用程序。应用程序1是一个网页应用,而应用程序2和应用程序3则是一些下载数据的脚本。
这三个应用都需要用到一个叫Common的模块,这个模块里有一些“模型”(就是保存到数据库里的类)和一些公共设置。
我对如何组织这个项目一点头绪都没有。我可以为每个应用创建三个文件夹,然后把Common复制三遍到它们各自的文件夹里(这样做感觉不太对)。
我想到的另一个办法是,创建一个主文件夹,把Common里的所有文件放进去,包括__init__.py。然后再创建三个子文件夹(子模块),每个应用一个。
还有一种方法是用pip安装Common,但这样的话每次我修改这个模块的时候都得重新安装。
在之前的项目中,我用过.NET - 在那个环境里,相当于有一个解决方案,里面有四个项目,其中一个就是Common。
有没有什么建议呢?
4 个回答
我会创建一个这样的结构:
project_root/
app1/
__init__.py
script.py
common/
__init__.py
models.py (all "common" models)
app1/script.py
import os, sys
# add parent directory to pythonpath
basepath = os.path.join(os.path.dirname(os.path.abspath(__file__)), '..')
if basepath not in sys.path:
sys.path.append(basepath)
from common.models VeryCommonModel
print VeryCommonModel
如果你不想在运行时设置 Python 路径,可以在运行脚本之前设置 Python 路径:
$ export PYTHONPATH=$PYTHONPATH:/path/to/project_root
然后你就可以这样做:
python app1/script.py
我喜欢这种方法。
projects/
__init__.py
project1/
__init__.py
project2/
__init__.py
lib1/
__init__.py
libfile.py
lib2/
__init__.py
所以,我需要进入项目文件夹。
要启动一个项目,可以使用
python -m project_name
这样我就可以轻松地从任何外部库导入,比如
from lib1.libfile import [imoprt what you want]
或者
from lib1 import libfile
把你的应用程序变成标准的Python模块。我推荐这样的结构:
apps/
common/
setup.py
common/
__init__.py
models.py
app1/
setup.py
app1/
__init__.py
models.py
project/
requirements.txt
这是一个基本的setup.py文件,用于你的公共应用:
#!/usr/bin/env python
from setuptools import setup, find_packages
setup(
name='common',
version='1.0.0',
packages=find_packages(),
zip_safe=False,
)
为其他应用也做一个类似的setup.py文件。
在requirements.txt中,为你的应用设置可编辑的“-e”选项:
-e apps/common
-e apps/app1
使用pip安装依赖:
$ pip install -r requirements.txt
可编辑选项的意思是,源文件会链接到Python环境中。你对应用的源文件做的任何修改都会立即生效,而不需要重新安装。
现在你可以在任何地方(其他应用、项目文件等)导入你公共应用中的模块(或者其他任何应用中的模块)。
我有一个类似的项目,结构是这样的:
project_root/
App1/
__init__.py
FlaskControlPanel/
app.py
static/
templates/
models/
__init__.py
mymodels.py
然后,我从 project_root
目录运行所有东西。我有一个小脚本(根据我的环境是批处理脚本或shell脚本),它设置 PYTHONPATH=.
,这样导入的模块才能正常工作。这样做是因为我通常在使用PyCharm开发时,导入的模块“就能正常工作”,但当我部署最终产品时,路径和我在IDE中的设置不一样。
一旦 PYTHONPATH
被设置为包含项目根目录下的所有内容,你就可以进行标准的模块导入了。
例如,在我的 FlaskControlPanel 的 app.py
文件中,我有这一行:
from models.mymodels import Model1, Model2, Model3
在 App1 的 __init__.py
文件中,我有完全相同的导入语句:
from models.mymodels import Model1, Model2, Model3
我可以通过在命令行(在Windows上)中运行以下命令来启动Flask应用,前提是我在 project_root
目录下:
setlocal
SET PYTHONPATH=.
python FlaskControlPanel\app.py
setlocal
用来确保 PYTHONPATH
只在这个会话中被修改。