包都装不上你写个锤子代码,N种姿势教你装包!

重磅干货,第一时间送达

选自《Python疑难杂症集》

作者:偷天神猫

来源:https://zhuanlan.zhihu.com/p/70776169

有的 Pythoner 看到这个题目可能要指着作者笑:装包还需要你教?

pip install package一键搞定有木有?

但据不完全统计,即使在 pip 如此流行的今天,包安装问题依然困扰着大部分的 Python 新手,本人也经常帮一些工作经验三四年的 Python 开发同事解决包安装的问题。

那么接下来我们看下不同场景下python装包的解决方法:

1. 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%的装包问题了

2. Medium模式

如果你安装过某些用c语言编写的python包,会发现上一步的做法并不能安装成功,命令窗口弹出诸如下面的报错。如果你连这个错误都没遇到过,那说明你做的python项目真不多

fatal error: Python.h: No such file or directory

那装不上到底是为什么呢??

根据本文主题,我将python三方包粗略分为两类:

1. 纯 Python编写的软件包 2. 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.4 [1]

如果你实在觉得麻烦,还有一个网站专门提供windows下的各种python包,可在不具备编译环境的情况下,选择合适自己的python环境进行安装,使用方法非常简单,pip install xxx.whl即可。网址如下,不谢

Unofficial Windows Binaries for Python Extension Packages [2]

这个站点虽然不是万能的,但应付大部分在windows下开发的pythoner已经绰绰有余了。不过据本人亲身体会,一些的特定版本的包这个站点还真没有,所以我常用的开发模式其实是windows下跑ide,代码则共享至linux下运行,因为大家实际部署生产环境也是在linux,总之怎么舒服怎么来。

另外,有些包是需要相应的工具依赖的,例如pynmap,要求系统先安装了nmap,用的人一定要心里有数,不然可能将大量时间浪费在环境配置上。

3. Hard模式

3.1 需求一

想象在某个极其恶劣的环境,老板给你提出了一个很不人道的需求:

小王,申请的服务器下来了,去把代码部署下吧

于是在某个风雨交加的晚上,你开始连接至生产服务器,手动部署代码,想着10分钟后就可以下楼撸串了,心里还有点小激动呢。然而登上服务器才发现:

1. 生产服务器无法访问外网 2. 公司搭建的内网pip源压根就不能用或者太久没更新压根就没你要的包

这时候真是叫天天不应,叫地地不灵。这种情况多见于国内的中、大型企业,有严格的网段划分和权限控制,但某些方面又做的不够好,比如源的管理问题。但活还是要干的,怎么办?

方法一:

先将各个所需的三方包下载至本地,然后上传至服务器,挨个pip install。这里提醒一句,其实pip install package 或 pip install -r requirements.txt时,目标可以是包名,也可以是包的安装目录,所以聪明的pythoner,怎么提高效率你懂的:)

方法二:

直接将三方包打包至项目代码中,简单粗暴,缺点是增加了项目代码体积

3.2 需求二:

在某个风和日丽的早晨,领导说:

小王啊,我们有个脚本需要部署到其他运维的服务器当agent用。

然后你经过调查发现脚本里面要用到一个三方包,但对方的服务器可能装过也可能没装过,于是你在脚本运行初始阶段设置了一个逻辑:

if xxx_package is exist:

import xxx

start run code

else:

pip install xxx_package

import xxx

start run code

然后你傻乎乎的调用了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

4. 写在最后

至此,你已经基本领略了 Python 装包 99% 以上的姿势,可以开开心心的 coding 了。如果你上面的都看完了,那么可以看下我一开始就想推荐的一篇文章,有点老,但通过了解python包管理工具的历史你对上述内容的理解会更深刻,同时又能体会到今天的世界是多么的美好。

Python 包管理工具解惑 [3]

当然,对于“包无法安装”这个问题,如果你还有其他更好的解决方案,或者对本文章有批评、指正或疑虑的地方,可在评论中指出,以便于我更新改正,谢谢大家。

References

[1] Microsoft Visual C++ Compiler for Python 3.4:  https://stackoverflow.com/questions/29909330/microsoft-visual-c-compiler-for-python-3-4

[2] Unofficial Windows Binaries for Python Extension Packages:  https://www.lfd.uci.edu/~gohlke/pythonlibs/

[3] Python 包管理工具解惑:  https://blog.zengrong.net/post/python_packaging/

这几个叼炸天的笔记软件你用过了么?

6个月达不到25.6万年薪AI工程师,进不了大厂全额退款

我来评几句
登录后评论

已发表评论数()

相关站点

+订阅
热门文章