python系列&deep_study系列:Python3.9安装uWSGI解决libpython3.9.a不存在




在这里插入图片描述

Python3.9安装uWSGI解决libpython3.9.a不存在

Python3.9安装uWSGI失败

前几天突然收到阿里云的邮件,我的轻量应用服务器马上到期,一查发现,学生优惠不复存在,续费价格翻了10倍,只好暂时新购一台腾讯云的服务器作为权衡之计,然后慢慢思考长期白嫖的办法。由于我的服务器上一直运行着网站,所以不得不花很多精力去做迁移。

之前服务器上的网站使用的是Django做后端,用的是Nginx和uWSGI做web server。迁移环境的时候,为了紧跟时代潮流我作了一下死,打算把环境从Python3.7.3迁移到Python3.9.7以享受更多的语法,然后就跳进了一个大坑。在安装uWSGI时出现以下编译错误(注意我两台服务器的操作系统都是CentOS7,别的系统会不会出这个问题我不敢保证):

ip install uwsgi
------------------------------------------------------------------------------------------------------------
Command errored out with exit status 1:
/root/softwares/anaconda3/lib/python3.9/config-3.9-x86_64-linux-gnu/libpython3.9.a no such file or directory

网上所有的方法都解决不了,包括:使用conda安装uwsgi、安装python3-devel、从uwsgi源码手动编译安装。剩下唯一可行的方案就是降低Python版本,但我偏不想妥协,因为我的Anaconda的base环境是3.9,降版本无非是新建一个虚拟环境,那样每次还需要activate。本文记录的内容是从bash_history和浏览器搜索记录中勉强恢复的,可能不会一字不差,因为当时在忙第二天的组会PPT,所以没有及时记录。

和BUG死磕到底的解决方案

根据以上报错,我们发现问题很明确,就是找不到libpython3.9.a文件。我们知道.a文件在Linux中是静态库文件,另一个我们熟知的.so是动态库文件。那之前服务器上Python3.7就不缺这个文件吗?首先进入到Python3.7的环境下,然后使用which查看Python的位置:

conda activate python37 && which python
----------------------------------------
/root/anaconda2/envs/python37/bin/python

那么参考上面的报错,分析存储.a文件的路径应为:

ls /root/anaconda2/envs/python37/lib/python3.7/config-3.7m-x86_64-linux-gnu/
----------------------------------------------------------------------------
config.c     libpython3.7m.a  __pycache__       Setup
config.c.in  Makefile         python-config.py  Setup.local
install-sh   makesetup        python.o

结果发现还真有这个文件,试了很多版本之后发现,只有3.9没这个文件。网上查不到过多的资料,但偶然发现一个神奇的BUG文档:https://bugs.python.org/issue43103。里面赫然写着:

Most users don't build a static Python executable, so I propose to no longer build "static Python" by default and add --with-static-python option to the configure script.

大多数用户不会使用到静态库,所以你建议在3.10中不默认构建这个?那Python3.9是不是也是你建议的呢?于是我想到,只要我们重新编译Python就好了,只要不使用–without-static-libpython这个参数,就一定能得到.a文件。

从源码重新编译Python3.9.7

首先下载并解压Python3.9.7的源码:

wget -t 100 -c https://www.python.org/ftp/python/3.9.7/Python-3.9.7.tgz
tar -zxf Python-3.9.7.tgz 

然后确保工具库都已经安装:

yum -y install gcc wget gcc-c++ automake autoconf libtool libxml2-devel libxslt-devel perl-devel zlib zlib-devel libffi-devel openssl openssl-devel

然后进入到源码文件夹进行编译和安装:

cd Python-3.9.7/
./configure --prefix=/tmp/Python
make -j4
make install

注意这里我们只是为了得到Python的静态库文件,为了防止Python版本直接的串扰,我们将目标目录设置到/tmp中,使用-j4是因为我的CPU是两核四线程。编译之后会发现我们果然得到了.a文件,将其拷贝到报错的位置上:

cp /tmp/Python/lib/libpython3.9.a ~/softwares/anaconda3/lib/python3.9/config-3.9-x86_64-linux-gnu/

然后我这里使用的是uwsgi的源码安装,使用pip也是一样的,但是我预料到编译会有更多的问题,而pip每次都会下载新文件,比较浪费流量。

wget http://projects.unbit.it/downloads/uwsgi-latest.tar.gz
tar -zxf uwsgi-latest.tar.gz
cd uwsgi-2.0.20/
python uwsgiconfig.py --build

然后就会得到更多的报错:

libcrypt.so: undefined reference to `NSSLOWHASH_NewContext@NSSRAWHASH_3.12.3 ...

解决@NSSRAWHASH_3.12.3未定义

这里也查不到解决方案!但是我发现网上都提示要安装openssl-devel,但问题是我已经安装了。所以猜想是环境变量不太对,果然查看上面这个报错的详细信息会发现,uwsgi在编译的时候使用的是Anaconda的链接器:

/root/softwares/anaconda3/compiler_compat/ld

这可能是因为我系统上默认的Python是Anaconda下base环境的Python。系统默认的ld其实在这里:

which ld|xargs ls -l
---------------------------------------------------------------------------
lrwxrwxrwx 1 root root 20 1123 17:52 /usr/bin/ld -> /etc/alternatives/ld

那么我们只需要强制它使用系统ld就好了,我比较暴力地让Anaconda找不到它自己的ld:

mv /root/softwares/anaconda3/compiler_compat/ld /root/softwares/anaconda3/compiler_compat/ld_sav

然后重新build,发现刚刚的错误消失了,出现了另一个错误:

/usr/lib64/libstdc.so.6: undefined reference to ‘__cxa_throw_bad_array_new_length@CXXABI_1.3.8

升级libstdc.so.6

这个问题就很常见了,是因为系统的libstdc.so.6的版本不够高。

strings /usr/lib64/libstdc++.so.6|grep CXXABI
---------------------------------------------
CXXABI_1.3
CXXABI_1.3.1
CXXABI_1.3.2
CXXABI_1.3.3
CXXABI_1.3.4
CXXABI_1.3.5
CXXABI_1.3.6
CXXABI_1.3.7
CXXABI_TM_1

可以发现这个文件是链接到6.0.19版本的库文件的:

ls -l /usr/lib64/libstdc++.so.6
---------------------------------------------------------------------------------------------------
lrwxrwxrwx 1 root root 30 221 21:12 /usr/lib64/libstdc++.so.6 -> /usr/lib64/libstdc++.so.6.0.19

我们从这里下载高版本的库文件:libstdc++.so.6.0.26.zip,下载完解压,将libstdc++.so.6.0.26移动到/usr/lib64下,然后删除原来的文件,重新进行软链接:

rm /usr/lib64/libstdc++.so.6
ln -s /usr/lib64/libstdc++.so.6.0.26 /usr/lib64/libstdc++.so.6

然后重新build,报了另外一个错误:

uwsgi: error while loading shared libraries: libicui18n.so.58

修复libicuuc.so.58环境

通过locate命令,我们查找到系统中这个库的位置:

locate libicui18n.so.58
-------------------------------------------------------------------------
/root/softwares/anaconda3/lib/libicui18n.so.58
/root/softwares/anaconda3/lib/libicui18n.so.58.2
/root/softwares/anaconda3/pkgs/icu-58.2-he6710b0_3/lib/libicui18n.so.58
/root/softwares/anaconda3/pkgs/icu-58.2-he6710b0_3/lib/libicui18n.so.58.2

我们只需要把以上路径软链接到系统的lib目录下即可:

ln -s /root/softwares/anaconda3/lib/libicui18n.so.58 /usr/lib64/libicui18n.so.58
ln -s /root/softwares/anaconda3/lib/libicui18n.so.58.2 /usr/lib64/libicui18n.so.58.2

然后再次build,发现大功告成!!!最后不要忘记将Anaconda的ld移动回来:

mv /root/softwares/anaconda3/compiler_compat/ld_sav /root/softwares/anaconda3/compiler_co

底下评论

问题一:

conda install -c conda-forge uwsgi 即可解决

其他人提问

为什么我用这个命令,conda直接100%占用cpu,与服务器卡死呢?

其他人提问

折腾了好几天,这个命令解决了我的问题![赞]

问题二:

大佬,我也是遇到这个问题了。使用“conda install -c conda-forge uwsgi”安装也过不去,使用大佬的自行编译方法,将libpython3.9.a拷到conda的包目录下就行了

问题三:

我用的版本是3.8 和答主出现一样的报错,奈何看着修复过程有点过于复杂,没做尝试,使用了评论区大佬的方案(conda install -c conda-forge uwsgi ),顺利装上了,感谢两位。







清川​

Python3.9安装uWSGI解决libpython3.9.a不存在

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

坦笑&&life

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值