有的pythoner看到这个题目可能要指着作者笑:装包还需要你教?pip install package一键搞定有木有?
但据不完全统计,即使在pip如此流行的今天,包安装问题依然困扰着大部分的python新手,本人也经常帮一些工作经验三四年的python开发同事解决包安装的问题-_-!。那么接下来我们看下不同场景下python装包的解决方法:
Easy模式
通常情况下,你只需要键入以下命令即可安装成功,package为需要安装的包名:
pip install package
但有时候因为网络问题,并无法安装成功,毕竟pip默认的官网源在国外,这时候我们可以使用国内的pip源,你会感受到飞一般的下载速度。我常用的是aliyun的pip源,当然国内还有很多其他源供你选择,在此就不一一列出了。
切换国内源分为临时性和永久性两种,如果只是该次使用,在命令行后添加相应参数即可:
# 指定包名安装
pip install package -i http://mirrors.aliyun.com/pypi/simple/ --trusted-host mirrors.aliyun.com
# 依据requirements.txt安装
pip install -r requirements.txt -i http://mirrors.aliyun.com/pypi/simple/ --trusted-host mirrors.aliyun.com
如果是想永久切换,可通过修改pip配置文件来达到此目的:
linux下修改~/.pip/pip.conf,如果没有该文件则创建;
windows下修改%HOMEPATH%\pip\pip.ini,如果没有则创建;
[global]
trusted-host=mirrors.aliyun.com
index-url=http://mirrors.aliyun.com/pypi/simple/
至此,我们已经能解决60%的装包问题了
Medium模式
如果你安装过某些用c语言编写的python包,会发现上一步的做法并不能安装成功,命令窗口弹出诸如下面的报错。如果你连这个错误都没遇到过,那说明你做的python项目真不多
fatal error: Python.h: No such file or directory
那装不上到底是为什么呢??
根据本文主题,我将python三方包粗略分为两类:
- 纯python编写的软件包
- c/c++语言编写的软件包
针对第二类情况,你需要确保系统上有对应的c/c++编译器及python开发者工具才能装包成功。
linux各个发行版,要先确保gcc、g++已经安装,然后再安装python开发者工具,以redhat/centos为例:
yum install gcc gcc-c++
yum install python-devel
# 或安装对应python版本的开发者工具
yum install python3-devel
yum install python36-devel
Debian/Ubuntu dev工具名字稍有不同,但思路一样
apt-get install python-dev
windows则需要安装vc++ for python x.x(即python对应的版本号),或者使用MinGw进行编译,参考阅读
Microsoft Visual C++ Compiler for Python 3.4stackoverflow.com
如果你实在觉得麻烦,还有一个网站专门提供windows下的各种python包,可在不具备编译环境的情况下,选择合适自己的python环境进行安装,使用方法非常简单,pip install xxx.whl即可。网址如下,不谢
https://www.lfd.uci.edu/~gohlke/pythonlibs/www.lfd.uci.edu
这个站点虽然不是万能的,但应付大部分在windows下开发的pythoner已经绰绰有余了。不过据本人亲身体会,一些的特定版本的包这个站点还真没有,所以我常用的开发模式其实是windows下跑ide,代码则共享至linux下运行,因为大家实际部署生产环境也是在linux,总之怎么舒服怎么来。
另外,有些包是需要相应的工具依赖的,例如pynmap,要求系统先安装了nmap,用的人一定要心里有数,不然可能将大量时间浪费在环境配置上。
Hard模式
需求一:
想象在某个极其恶劣的环境,老板给你提出了一个很不人道的需求:
小王,申请的服务器下来了,去把代码部署下吧
于是在某个风雨交加的晚上,你开始连接至生产服务器,手动部署代码,想着10分钟后就可以下楼撸串了,心里还有点小激动呢。然而登上服务器才发现:
- 生产服务器无法访问外网
- 公司搭建的内网pip源压根就不能用或者太久没更新压根就没你要的包
这时候真是叫天天不应,叫地地不灵。这种情况多见于国内的中、大型企业,有严格的网段划分和权限控制,但某些方面又做的不够好,比如源的管理问题。但活还是要干的,怎么办?
方法一:先将各个所需的三方包下载至本地,然后上传至服务器,挨个pip install。这里提醒一句,其实pip install package 或 pip install -r requirements.txt时,目标可以是包名,也可以是包的安装目录,所以聪明的pythoner,怎么提高效率你懂的:)
方法二:直接将三方包打包至项目代码中,简单粗暴,缺点是增加了项目代码体积
需求二:
在某个风和日丽的早晨,领导说:
小王啊,我们有个脚本需要部署到其他运维的服务器当agent用。
然后你经过调查发现脚本里面要用到一个三方包,但对方的服务器可能装过也可能没装过,于是你在脚本运行初始阶段设置了一个逻辑:
请仔细阅读以上代码
然后你傻乎乎的调用了python的系统命令来执行包的安装操作,诸如os.system/os.popen/subprocess.Popen,发现并没有什么卵用,包确实执行安装了,但是代码初次运行的环境还是检测不到该包的存在,wtf?
经过一番分析发现,安装发生在脚本启动之后,上述安装方法并不会将新安装的包同步至当前的运行过程中,因为python脚本是在启动之初就将import的包导入当前内存中的,也就是说我们新安装的并没有被热更新过来,归根结底是因为动态装包的姿势不对,下面给出动态装包的代码示例,重点在于install函数部分,当年我可是在这个坑了待了好久才出来,说多了都是泪!_!:
import pip
def install(package):
if hasattr(pip, 'main'):
pip.main(['install', package])
else:
pip._internal.main(['install', package])
# Example
if __name__ == '__main__':
try:
import xxx
print('Yeah, the package is here, ready go')
# todo run main code
except ImportError:
print('oh no, it seems like you must install this package then you can use it')
install('xxx')
# todo run main code
结语
至此,你已经基本领略了python装包99%以上的姿势,可以开开心心的coding了。如果你上面的都看完了,那么可以看下我一开始就想推荐的一篇文章,有点老,但通过了解python包管理工具的历史你对上述内容的理解会更深刻,同时又能体会到今天的世界是多么的美好。
Python 包管理工具解惑blog.zengrong.net
当然,对于“包无法安装”这个问题,如果你还有其他更好的解决方案,或者对本文章有批评、指正或疑虑的地方,可在评论中指出,以便于我更新改正,谢谢捧场?