我目前使用的 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 来打包自己的项目,但是还是想了解下,这样的布局方式是否有合理?
能否给一个例子参考,谢谢大神们了。
1
gladuo 2015-10-19 17:55:28 +08:00
看看几本 django 类的书吧,比如 two scopes of django 什么的,讲的还不错。
|
2
siteshen 2015-10-19 18:27:39 +08:00 1
下面是我们的代码结构。
├── 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 不太可思议。 |
3
DiffView 2015-10-19 19:13:03 +08:00
|
4
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 一个完整的,独立的项目,目录结构一看就懂。 |
5
zhicheng 2015-10-19 19:23:03 +08:00
注意 nginx.conf 和 supervisord.conf 并不是完整的配置,而是针对项目的 Server 和 App 的定义,部署的时候要 link 到相应的 /etc/nginx/conf.d /etc/supervisord/conf.d/ 里面。
|
6
ChiangDi 2015-10-19 19:25:17 +08:00
rails new 飘过,啥都不用管,最佳实践。
|
7
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(安装本地环境的脚本) |
8
felixzhu 2015-10-19 19:26:43 +08:00
擦,编辑器把我的所有空格缩紧都删掉了。。。。楼主大概看看吧反正也都差不多。。
|
9
aiqier OP |
11
zhicheng 2015-10-19 23:39:53 +08:00
@aiqier 没有扩展名的是目录,只有一层 Python 。如果通过目录名字猜不到里面是啥,那估计也不太适合做程序员了。
|
15
aiqier OP @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? |
16
zhicheng 2015-10-20 16:21:02 +08:00 1
@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 $ |