V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
aiqier
V2EX  ›  Python

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

  •  3
     
  •   aiqier · 2015-10-19 16:21:20 +08:00 · 4812 次点击
    这是一个创建于 3315 天前的主题,其中的信息可能已经有所发展或是发生改变。

    我目前使用的 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 来打包自己的项目,但是还是想了解下,这样的布局方式是否有合理?

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

    17 条回复    2015-10-20 16:32:24 +08:00
    gladuo
        1
    gladuo  
       2015-10-19 17:55:28 +08:00
    看看几本 django 类的书吧,比如 two scopes of django 什么的,讲的还不错。
    siteshen
        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 不太可思议。
    DiffView
        3
    DiffView  
       2015-10-19 19:13:03 +08:00
    https://github.com/robinxb/Simple-Flask-template-seed
    你可以参考下虽然是 Flask 的
    但是主要思路是把 app 实例化出来,在包外管理。
    zhicheng
        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

    一个完整的,独立的项目,目录结构一看就懂。
    zhicheng
        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/ 里面。
    ChiangDi
        6
    ChiangDi  
       2015-10-19 19:25:17 +08:00
    rails new 飘过,啥都不用管,最佳实践。
    felixzhu
        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(安装本地环境的脚本)
    felixzhu
        8
    felixzhu  
       2015-10-19 19:26:43 +08:00
    擦,编辑器把我的所有空格缩紧都删掉了。。。。楼主大概看看吧反正也都差不多。。
    aiqier
        9
    aiqier  
    OP
       2015-10-19 23:26:55 +08:00
    @siteshen 我的
    "外引内,内引外"是指,对于这样一个目录:
    ── a.py
    ├── b
    │   └── c.py

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

    我的 utils 用来保存一些自己经常使用的工具类,这都是编写代码时间长了之后的“自我经验”库。
    aiqier
        10
    aiqier  
    OP
       2015-10-19 23:27:59 +08:00
    @zhicheng 大哥,这个没显示层级啊,,,
    zhicheng
        11
    zhicheng  
       2015-10-19 23:39:53 +08:00
    @aiqier 没有扩展名的是目录,只有一层 Python 。如果通过目录名字猜不到里面是啥,那估计也不太适合做程序员了。
    aiqier
        12
    aiqier  
    OP
       2015-10-20 15:36:44 +08:00
    @zhicheng 。。。。那你是将项目路径配置到跟 pythonPath 中?然后在内部直接绝对导入的?
    aiqier
        13
    aiqier  
    OP
       2015-10-20 15:38:48 +08:00
    @felixzhu 是将项目根路径添加到 pythonpath 中吗?
    zhicheng
        14
    zhicheng  
       2015-10-20 15:50:47 +08:00
    @aiqier 为什么要加到 PythonPath 里?
    aiqier
        15
    aiqier  
    OP
       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
        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
    $
    aiqier
        17
    aiqier  
    OP
       2015-10-20 16:32:24 +08:00
    @zhicheng 那你的意思就是只要把主控(main.py)放到根目录就行了?
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2887 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 29ms · UTC 06:33 · PVG 14:33 · LAX 22:33 · JFK 01:33
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.