如何合理的规划一个 python 的项目目录?

2015-10-19 16:21:20 +08:00
 aiqier

我目前使用的 web 框架是 tornado ,用它来搭建 server ,我目前的项目文档是这样的(有些抄袭 flask 的框架):

└── myweb
├── fab.py
├── init.sh
├── log
└── myweb
├── README.md
├── apps
│ ├── config.py
│ ├── datadict.py
│ ├── handlers
│ ├── main.py
│ └── orm
├── samples
├── sql
├── tests
└── utils

myweb 为项目名称,其中内部的 myweb 目录为一个完整的项目包,最外部的 myweb 目录,除了包括此项目,还有 init.sh 用来做项目初始化的某些工作, log 用来保存日志, fab.py 是 fabric 命令的文件。

目前能满足基本的需求,但是我想把它弄的更“专业化”。而且我一直好奇我所遇到的问题有没有更好的解决办法。

1.python 的 import ,“外引内”容易,但是“内引外”会很复杂。我没有用相对引用(“..”的方式向上引用),首先那种写法太挫了,再说 python 官方也不建议用那种写法。我目前的做法是吧 myweb 作为一个项目的根目录,直接添加到 python 的 PATH 目录中,如果是 supervisor ,那就配置给 directory 就行了, myweb 作为根的好处就是其它部分去 import 模块会非常容易(直接用绝对引用, import 就行了)。

2.我们的项目经常要发布到专门的服务器上进行测试,我的做法是直接使用 fabric 发布到测试服务器部署,但是并非完全的自动化部署,自动化运运行单元测试,是否有更好的解决方案?

3.我项目的内部和外部都有一个 myweb 文件夹,外部的算整个代码库( git 管理),而内部的算一个完整的 python 包,我目前还未想过使用 egg 来打包自己的项目,但是还是想了解下,这样的布局方式是否有合理?

能否给一个例子参考,谢谢大神们了。

4778 次点击
所在节点    Python
17 条回复
gladuo
2015-10-19 17:55:28 +08:00
看看几本 django 类的书吧,比如 two scopes of django 什么的,讲的还不错。
siteshen
2015-10-19 18:27:39 +08:00
下面是我们的代码结构。

├── README.md
├── conf
│   └── init
├── myweb
│   ├── app
│   │   ├── api
│   │   ├── form
│   │   └── page
│   ├── batch
│   ├── config
│   ├── logic
│   ├── model
│   ├── util
│   └── worker
├── requirements.lock
├── requirements.txt
├── scripts
└── test

我们用的 flask 框架, model, logic, util, config 为 app/worker/batch 所共享
config - 时区, db , redis 配置
util - string, datetime, 定义 redis_client 等
model - 数据层
logic - 业务逻辑(如关注用户发送 push notification 在次调用)
app - 为“前端”(主要是客户端 API 和后台管理界面)服务
worker - 异步任务(发短信, push notification 等)
batch - 定时任务(定期同步 redis 数据到 db 等)
fabfile.py - 部署,查看数据库状态等
conf - 代码无关的配置( ssh_config , authorized_keys , app 启动脚本等)

======

1. python import 如果不做 library 用绝对路径挺好,看着整洁;作为 library 发布的话,用相对路径比较好,不强制用户使用你定义的包名(比如项目里要用到两个都名为 requests 的包,绝对路径就不方便迁移);“外引内”,“内引外”表示没看懂。
2. fabfile.py 直接写几个函数做测试还行, fab deploy_stage 一个命令也是足够自动化了吧。
def deploy(): run_unit_test(); restart_server()
def deploy_stage(): run_unit_test(); restart_server()
3. 我们也是这么做的,服务器都是我们可控制的,没那必要打包。不过你的 utils 我没太明白,是 python 要用的还是其他的脚本,如我的 scripts 目录? python 代码里居然没有 util.py 不太可思议。
DiffView
2015-10-19 19:13:03 +08:00
https://github.com/robinxb/Simple-Flask-template-seed
你可以参考下虽然是 Flask 的
但是主要思路是把 app 实例化出来,在包外管理。
zhicheng
2015-10-19 19:21:37 +08:00
(env)$ tree -L 1
.
├── alembic
├── alembic.ini
├── backup
├── bootstrap.sh
├── cache
├── contrib
├── dbmigrate.sh
├── define.py
├── development.conf
├── env
├── fabfile.py
├── handlers
├── image
├── langs
├── logs
├── main.py
├── migrate
├── models
├── nginx.conf
├── production.conf
├── requirements.txt
├── static
├── supervisord.conf
└── templates

一个完整的,独立的项目,目录结构一看就懂。
zhicheng
2015-10-19 19:23:03 +08:00
注意 nginx.conf 和 supervisord.conf 并不是完整的配置,而是针对项目的 Server 和 App 的定义,部署的时候要 link 到相应的 /etc/nginx/conf.d /etc/supervisord/conf.d/ 里面。
ChiangDi
2015-10-19 19:25:17 +08:00
rails new 飘过,啥都不用管,最佳实践。
felixzhu
2015-10-19 19:25:38 +08:00
我也贴一下我自己项目的一个大概吧,不过因为我都是独立开发所以相对来说随意一点,具体的还是要看项目的

├── {project}
| # 1. Controller
│ └── api(移动端 Rest API 都写在这里)
│ └── fields
│ └── serializers
│ └── apiv1(因为移动端的接口必须保证老版本可用,所以 api 用多个文件夹)
│ └── account.py
│ └── product.py
│ └── exceptions.py
│ └── permissions.py
│ └── urls.py
│ └── ...
│ └── www(网页都写在这里)
│ └── views
│ └── forms
│ └── urls.py
│ └── cms(cms 系统, 假设使用 angular.js 开发)
│ └── api
│ └── www
│ └── src
│ └── app
│ └── config
│ └── directive
│ └── filter
│ └── modals
│ └── service
│ └── modules
│ └── assets
│ └── styles
│ └── index.js
│ └── bower.json
│ └── gulp
│ └── gulpfile.js
│ └── ...
│ └── crm(crm 系统)
│ └── bi(bi 系统)
| # 2. Service
│ └── auth(登录服务)
│ └── search(搜索服务)
│ └── ratelimits(频率控制服务)
| # 3. 全局代码
│ └── models(模型)
│ └── middleware(中间件)
│ └── cache(缓存相关)
│ └── db(数据库相关, Models 和 Manager 等基本类)
│ └── templates(模版)
│ └── utils(通用的一些工具类,或者对默认库的一些修改)
| # 4. 配置
│ └── migrations(数据库操作记录)
│ └── settings(相关配置文件)
│ └── urls.py
│ └── dev.py
│ └── prod.py
| # 5. 测试
│ └── testdb(生成测试数据)
├── docs(文档)
├── tests(测试代码)
└── install.sh(安装本地环境的脚本)
felixzhu
2015-10-19 19:26:43 +08:00
擦,编辑器把我的所有空格缩紧都删掉了。。。。楼主大概看看吧反正也都差不多。。
aiqier
2015-10-19 23:26:55 +08:00
@siteshen 我的
"外引内,内引外"是指,对于这样一个目录:
── a.py
├── b
│   └── c.py

如果 a 想引用 c ,那么 from b import c 就行了,(外引内)
但是 c 想引用 a ,就很麻烦(内引外)

我的 utils 用来保存一些自己经常使用的工具类,这都是编写代码时间长了之后的“自我经验”库。
aiqier
2015-10-19 23:27:59 +08:00
@zhicheng 大哥,这个没显示层级啊,,,
zhicheng
2015-10-19 23:39:53 +08:00
@aiqier 没有扩展名的是目录,只有一层 Python 。如果通过目录名字猜不到里面是啥,那估计也不太适合做程序员了。
aiqier
2015-10-20 15:36:44 +08:00
@zhicheng 。。。。那你是将项目路径配置到跟 pythonPath 中?然后在内部直接绝对导入的?
aiqier
2015-10-20 15:38:48 +08:00
@felixzhu 是将项目根路径添加到 pythonpath 中吗?
zhicheng
2015-10-20 15:50:47 +08:00
@aiqier 为什么要加到 PythonPath 里?
aiqier
2015-10-20 16:12:28 +08:00
@zhicheng 就这个项目结构而言:
── autopayment
│   ├── __init__.py
│   ├── __init__.pyc
│   ├── apps
│   │   ├── __init__.py
│   │   ├── __init__.pyc
│   │   ├── business
│   │   │   ├── __init__.py
│   │   │   ├── __init__.pyc
│   │   │   ├── base.py
│   │   │   ├── base.pyc
│   │   │   ├── sp
│   │   │   │   ├── __init__.py
│   │   │   │   ├── __init__.pyc
│   │   │   │   ├── icbc.py
│   │   │   │   └── icbc.pyc
│   │   │   ├── sp_decision.py
│   │   │   └── sp_decision.pyc
│   │   ├── const.py
│   │   ├── const.pyc
│   │   ├── handler

handler 里面的文件,要导入 base.py ,如果想这样写: from autopayment.apps.business import base
就只能把 autopayment 的路径添加到 pythonpath 了,难倒还有别的方式导入 base?
zhicheng
2015-10-20 16:21:02 +08:00
@aiqier

$ tree autopayment/
autopayment/
├── apps
│   ├── __init__.py
│   ├── __init__.pyc
│   ├── business
│   │   ├── __init__.py
│   │   ├── __init__.pyc
│   │   ├── base.py
│   │   └── base.pyc
│   └── handler
│   ├── __init__.py
│   ├── __init__.pyc
│   ├── hello.py
│   └── hello.pyc
└── main.py

3 directories, 11 files
$ cat autopayment/main.py
from apps.handler import hello
print hello.foobar
$ cat autopayment/apps/business/base.py
foobar = "hello,world"
$ cat autopayment/apps/handler/hello.py
import apps.business.base
foobar = apps.business.base.foobar
$ python autopayment/main.py
hello,world
$
aiqier
2015-10-20 16:32:24 +08:00
@zhicheng 那你的意思就是只要把主控(main.py)放到根目录就行了?

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/229241

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX