每一个pythoner都知识pip install,安装python模块实现是方便。
当一个应用扩展十几二十个python模块时,网上最流行的方法是这样的:
1、pip freeze > requirements.txt将包依赖信息保存在requirements.txt文件中。
requirements.txt文件的内容大概是这样的:
blinker==1.3
Flask==0.10.1
Flask-Babel==0.9
Flask-Login==0.2.11
Flask-Mail==0.9.1
Flask-OpenID==1.2.4
Flask-Redis==0.0.6
Flask-RESTful==0.3.2
Flask-Session==0.1.1
Flask-WTF==0.11
flup==1.0.2
2、然后在部署时,首先请出virtualenv这尊大神,使用:
> virtualenv myenv
建立一个python的隔离环境
3、然后在命令行执行 myenv\scripts\activate进入该隔离环境.
4、最后
pip install -r requirements.txt
这样万事大吉,一个安装部署大体就完成了。
但在天朝这事情貌似没这么简单,pip安装的文件是从位于国外的pypi.python.org下载的,因此就比较悲剧了,上述上方法几乎难以有效运行。
从pypi安装速度超慢,不稳定,timeout是经常的。
而上述安装部署方法,还有一个问题,就是某些python模块是需要编译的,如果用户环境编译环境没有安装配置合适,安装模块也是比较容易失败的。
另外由于有一些python模块会升级,可能会带来不兼容,因而可能导致一些意想不到的问题。
又由于升级等原因,找不到对应的模块导致安装失败。
总之问题比较多,我希望安装部署是这样的:
1、能从本地文件夹进行安装,而不是在线安装。
2、应用总是依赖我开发时的模块,而不是最新的。
3、能在创建隔离环境后自动安装所有依赖模块。
4、避免进行安装时编译。
因此,当你的软件需要交付给不同的用户时,我目前使用的比较现实的python模块的安装部署方法是样,简单说一下思路:
1、将你所有需要依赖的python模块复制到install\libs,将编译过的模块按平台归类收集到一个文件夹中,如install\libs\windows\64bit。
2、接着自己建立virtualenv 的创建启动脚本,就是运行以下python代码,生成一个install\create.py的脚本文件。
import virtualenv, textwrap output = virtualenv.create_bootstrap_script(textwrap.dedent(""" import os, subprocess def after_install(options, home_dir): #在此处写你自己的脚本,主要就是复制文件和安装模块的命令
#此处的home-dir就是你创建的虚拟环境
#以下的是我写一些代码供参考
<pre name="code" class="python"> if sys.platform == 'win32': bin_path = 'Scripts' else: bin_path = 'bin' #安装需要编译的python模块,按平台进行复制
# 针对一些需要编译的模块,此处采用的是直接复制二进制包的方式 import platform,shutil bits,ostype=platform.architecture() ostype=platform.system() libs_path=os.path.join(os.path.dirname(__file__),"libs",ostype,bits) def copyFiles(sourceDir, targetDir): for file in os.listdir(sourceDir): sourceFile = os.path.join(sourceDir, file) targetFile = os.path.join(targetDir, file) if os.path.isfile(sourceFile): if os.path.splitext(sourceFile)[1]==".whl": subprocess.call([join(home_dir,bin_path, 'pip'),'install',sourceFile]) else: if not os.path.exists(targetDir): os.makedirs(targetDir) if not os.path.exists(targetFile) or(os.path.exists(targetFile) and (os.path.getsize(targetFile) != os.path.getsize(sourceFile))): open(targetFile, "wb").write(open(sourceFile, "rb").read()) if os.path.isdir(sourceFile): copyFiles(sourceFile, targetFile) for file in os.listdir(libs_path): fullname=os.path.join(libs_path,file) if os.path.isdir(fullname): print "installing %s......" % file , try: copyFiles(fullname,join(home_dir,'Lib',"site-packages")) print "OK!" except Exception,E: print "ERROR:%s" % E.message #不需要编译的python模块,直接调用pip install xxxx.tar.gz, libs=[ "Werkzeug-0.10.1.tar.gz", "Jinja2-2.7.3.tar.gz",#模板引擎 "Flask-0.10.1.tar.gz",#Flask "SQLAlchemy-0.9.9.tar.gz",#ORM "Flask-SQLAlchemy-2.0.tar.gz",#ORM "WTForms-2.0.2.tar.gz",#表单库 "Flask-WTF-0.11.tar.gz",#表单库 ] #开始依次安装 for lib in libs: lib_file=os.path.join(os.path.dirname(__file__),'libs',lib) subprocess.call([join(home_dir,bin_path, 'pip'),'install','--no-cache-dir','--no-deps','--disable-pip-version-check',lib_file])
f = open('create.py', 'w').write(output)
上面的代码会生成一个create.py的文件,然后你这个文件中找到after_install方法,自己修改。
基本思路就是从pypi.python.org下载对应的.tar.gz或.whl安装包,然后调用pip install xxxxxxxxx.tar.gz进行安装。
2、然后在命令行使用生成的create.py来创建隔离环境,如:
> python create.py myeny
按照上述方法,安装时就可以脱离pypi通过本地文件进行安装,相比较而言,更稳定些。