博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
把uliweb项目变成可安装的python包
阅读量:5889 次
发布时间:2019-06-19

本文共 3365 字,大约阅读时间需要 11 分钟。

hot3.png

这是目前我的一个尝试。随着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 uliwebfrom uliweb.utils.setup import setupimport 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。所以需要不升级就能解决的方法。

找来找去,有两个参考:

  1. 这个讨论(其它的地方也看到有相同的代码)中有一段使用ctypes写的symlink的函数实现,用它可以在windows下创建符号连接。
  2. 这个项目实现了好几种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的方法。

使用

其实前面已经写了:

  1. 执行 uliweb makeproject <projectname> 会在生成的 projectname 目录下创建一个setup.py文件。你可以打开修改它的内容以满足你的需要
  2. 执行 python setup.py installpython setup.py develop 来安装你的项目,这样就可以在其它的项目中使用了。使用方式是 import project.app,如果想反安装,如果是使用develop安装的话,可以这样 python setup.py develop -u 。但是使用install的话,报歉,没戏了。所以这时可以使用pip来做这事: pip uninstall <projectname> 。这也是我建议你两个都安装的原因,这两个工具互补还是不错的。

转载于:https://my.oschina.net/limodou/blog/165647

你可能感兴趣的文章
lintcode 单词接龙II
查看>>
Material Design学习之 ProgreesBar
查看>>
WEB版一次选择多个文件进行批量上传(WebUploader)的解决方案
查看>>
Redis之 命令行 操作
查看>>
Jvm(46),指令集----对象创建与访问指令
查看>>
如何直接强制客户端刷新.js文件
查看>>
【C#】窗体动画效果
查看>>
过滤器
查看>>
EL 表达式小结
查看>>
内部排序
查看>>
OEM java.lang.Exception null
查看>>
jQuery EasyUI API 中文文档 - 组合(Combo)
查看>>
10个关于 Dropbox 的另类功用(知乎问答精编)[还是转来了]
查看>>
Oracle体系结构
查看>>
用Modelsim仿真QII FFT IP核的时候出现的Error: Illegal target for defparam
查看>>
javascript Error对象详解
查看>>
orm Lite的使用
查看>>
项目经理的职责(转载)
查看>>
安装rabbitmq
查看>>
Excel中 设置使得每行的颜色不一样
查看>>