python 拆包装包_把uliweb项目变成可安装的python包

这是目前我的一个尝试。随着uliweb的项目多起来(为了便于管理和隔离,我们会考虑将不同的功能拆分为不同的项目),需要有时复用其它项目的模块,比如:用户管理等。uliweb项目是可以将一个满足条件的python包(使用 uliweb makeapp appname)作为外部的app在INSTALLED_APPS中配置的。但是对于使用 uliweb makeproject projectname 生成的项目,却缺省不是一个可以处理的python包,因此直接是无法在另一个项目中导入的,为了实现这一点,我对uliweb进行了优化。

设计安装方法和结构

为了让一个目录是可以导入的,我们一般会使用setup.py来编写一个安装脚本,在其中写上对应要安装的包和目录。一个uliweb的project是什么结构呢?

project/

apps/

settings.ini

app1/

app2/

wsgi_handler.py

我们所有的app都是放在apps目录下,所以它是一个重要的目录。比如我们的项目目录是project,因此对于app1这个app来说,我希望可以在安装后使用 import project.app1 来导入。那么我们会发现,希望导入的包名和实际的目录是不对应的。那么如何处理呢?

在写setup.py时,有两个变量很重要:packages和package_dir,它一个是用来表示安装后将出现的包名,可以是多个,另一个是一个配置,用来表示安装包与实际目录的关系。因此,我们可以这样写:

setup(packages=['project'], package_dir={'project':'apps'})

这样就告诉安装程序,在安装时创建包为project,但是它实际的文件是来自当前目录的apps下的内容。

考虑好这一点,我就开始改造uliweb。

改造uliweb

修改makeproject和项目模板

首先是考虑在执行makeproject时自动拷贝一个setup.py文件到新建的项目目录下。它的内容是:

import uliweb

from uliweb.utils.setup import setup

import apps

__doc__ = """doc"""

setup(name='{{=project_name}}',

version=apps.__version__,

description="Description of your project",

package_dir = {'{{=project_name}}':'apps'},

packages = ['{{=project_name}}'],

include_package_data=True,

zip_safe=False,

)

可以看到,它里面有一个变量 {{=project_name}} ,表示这个值将用实际的项目路径名进行替換。因此,如果我们执行 uliweb makeproject project 会在当前目录下生成 project 目录,在其中会有一个setup.py文件,makeproject命令会自动将模板中的 {{=project_name}} 替換为 project 。

然后我们还需要在apps下添加一个 __init__.py,它定义了 __version__ 变量值,这个值会用在 setup.py中。用来表示项目的版本。

改造安装脚本

使用setup.py来安装模块时主要有两种方式:install和develop。注意develop是setuptools中特有的。因此需要在你的环境中安装setuptools,同时还建议把pip也安装。最好的方式是使用virtualenv,它会自动安装这两个包。

对于install,它会把对应的文件全部拷贝到python的site-packages下,对于develop,它只会在site-packages下的easy_install.pth中加一个路径,不会真正拷贝。

对于install,因为会拷贝文件,所以不会有太大的问题。只不过如果你的项目经常更新,需要不停地执行install来更新。

因此,很多时候我会使用develop来安装。但是在实际处理过程中发现develop是存在问题的。主要问题就是不会进行实际文件的拷贝。因为我们的包结构和实际的目录结构不同,而拷贝的方式会创建这种结构,但是develop方式无法实现这种包结构。所以有问题。

那么怎么解决呢?我在网上搜了半天,终于找到一种办法,那就是创建: 符号连接 。符号连接是在linux下常用的一种方法。其实这种方法在windows下也是可以用的。有这么几个方法可以使用:

os.symlink(src, linkname) #创建src为linkname

os.path.islink(path) #检查path是事是一个link

os.unlink(path) #删除一个link或文件

但是,在windows平台下,这些方法除了unlink以外,都存在问题。看到网上说在python 3.2之后就可以了。但是我运行的环境主要是python 2.6和2.7。所以需要不升级就能解决的方法。

找来找去,有两个参考:

http://stackoverflow.com/questions/1447575/symlinks-on-windows 这个讨论(其它的地方也看到有相同的代码)中有一段使用ctypes写的symlink的函数实现,用它可以在windows下创建符号连接。

https://github.com/juntalis/ntfslink-python 这个项目实现了好几种windows下连接的支持,其中有symlink的支持(具体有哪些请自行研究吧)。这里面实现了上面的几个函数。

那么我的实现是写在 uliweb/utils/setup.py 中的,对原来的setuptools中的develop命令的几个方法进行了特殊处理,如:

install_for_development 我在它之后添加了根据setup中的packages和package_dir来创建符号连接的处理。它支持包和子包。因此你可以使用象

setup(packages=['project', 'project.batch'],

package_dir={'project':'apps', 'project.batch':'batch'})

这样的方式,将不同的目录处理到一个包结构之下。

uninstall_link 我在它之后増加了删除symlink的处理。原来的处理只会删除原来创建的文件,而不会删除新创建的连接。

因此,如果你要使用uliweb的develop方式,并且在windows下,你需要安装 ntfslink 这个包。为什么呢?

因为我发现,直接执行unlink去删除一个symlink会报 [Error 5] 的错误。而 ntfslink.symlink 中的unlink方法可以正确删除。但是我又发现,ntfslink.symlink 中的create好象无法创建正确的symlink,所以我还是使用了stackoverflow中的创建symlink的方法。

使用

其实前面已经写了:

执行 uliweb makeproject 会在生成的 projectname 目录下创建一个setup.py文件。你可以打开修改它的内容以满足你的需要

执行 python setup.py install 或 python setup.py develop 来安装你的项目,这样就可以在其它的项目中使用了。使用方式是 import project.app,如果想反安装,如果是使用develop安装的话,可以这样 python setup.py develop -u 。但是使用install的话,报歉,没戏了。所以这时可以使用pip来做这事: pip uninstall 。这也是我建议你两个都安装的原因,这两个工具互补还是不错的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值