本节目录
问题描述
我的Ubuntu又双叒叕炸了,起因是试图装caffe时总是报找不到pycaffe和pytest,上网查询发现有人说是numpy的问题,遂用pip3完全卸载所有版本的numpy(注意,只卸载一次的话可能有旧版残留)后安装Anaconda,安装过程完全遵照Anaconda安装官网的指导。尝试执行conda指令,结果无法正确运行,返回一堆traceback,conda init也一样。在试图解决conda无法正确运行的问题时,忽然发现Ctrl+Alt+T不管用了。不仅如此,连Ctrl+Alt+F2都不管用了。此外,按徽标键后输入terminal也不起作用。原以为只是GNOME运行时间长了出了故障,重启一下就好,结果又是只要登录就无法启用终端。有意思的是登录之前是可以切到tty2的,说明是登录后才出的问题。这个问题似乎没有其他的不良影响,浏览器什么的都还能运行。但是,只是用浏览器的话,我为啥要用Linux???这个问题真是很奇怪又不能不解决。
系统环境
Ubuntu 18.04 LTS, 内核5.3.0-28-generic
python版本:python3.7m
需要包:python3-dev,python3-apt
笔者的机器之前执行过pip3 install conda,不过似乎不太管用,直到今天试图安装Anaconda
操(瞎)作(蒙)过程
本段是笔者个人的实际操作记录,仅供后面总结出来的方法不起效时参考。如果总结的方法起效了就不用在乎这段。
笔者建议先阅读“总结”一段,如若不行再阅读这段。
查看~/.bashrc和/etc/profile
确认了是登录后才有问题,那么首先怀疑~/.bashrc的问题。重启一下进入tty2,直接把~/.bashrc里整个conda的启动代码注释掉,重启,没有任何用。说明不只是它出了问题。
检查/etc/profile和/etc/rc.local等常见配置文件,没有发现任何异常。
重装桌面管理器
在recover模式下先启用network再在root权限下卸载gdm3再重装,没有任何用。
换用miniconda
重启后登录前切到tty2(或者,如果这里没有网的话,试试在recover模式下操作),用w3m浏览器(一个命令行网页浏览器)在bing.com中搜索miniconda。这东西界面很简单明了,带方括号的控件可以按Enter交互。在文本框(TEXT)控件按回车,输入miniconda,再按回车,然后通过上下键选中SUBMIT按钮后再按回车就行了。其他网站也是一样的。
选好要下载的文件,安装过程和Anaconda没有区别。切到GNOME环境下再试试,emmm,依然不行。
换用lightdm
在ecover模式下卸载gdm3改用lightdm,reboot,进入lightdm的界面。试一下终端热键,emmmmmmm,还是不行……但是试试tty热键,发现这次至少能在登录后切到tty2,不用再反复重启折腾了。
查看conda状态
事后发现这一步可能不是很关键,但总之因为是conda引发的问题(网上很多讨论也佐证了这点),于是尝试运行conda。运行中发现了两个问题:
no module named apt_pkg
no module named conda
查询后发现了一个很简单的修复apt_pkg问题的方法。如下。
修复no module named apt_pkg
确定python目录
下面以python安装在/usr/local系列目录下为例,请用which确定你自己的python可执行文件目录。如果/usr/local下有相关文件,一般而言,/usr/local下的文件优先级比/usr下高,但不一定。可以查看PATH等环境变量确定这点。
获取apt_pkg
首先尝试
apt install python3-apt
如果已经安装的话说明当前python环境没有正确配置。如果这个指令确实安装了一些东西,现在试试conda指令是否不再报这个错误了(但是no module named conda大概还在。要是那个错误也消失了的话当然最好)。如果确实已经安装或安装完后仍然存在该问题,说明系统中一定已经存在这个东西,但是需要手动处理一下。
find /usr -name "apt_pkg*"
需要注意,没输出不代表系统里一定没有,需要的文件也许不在/usr目录下,请自行判断。
找到一个名字类似apt_pkg.cpython-x86_64-linux-gnu.so的东西后,把它复制到实际起效的python3.7m库目录(实践表明找python3.7的库目录就行,笔者的PC上没有/usr/local/lib/python3.7m但有/usr/local/lib/python3.7)下一个叫dist-packages的子目录(没有的话八成不是正确的目录,mkdir也不一定有效),创建一个名为apt_pkg.so的软链接,顺便把apt_pkg.pyi也复制过去:
cd /usr/local/lib/python3.7/dist-packages
cp /usr/lib/python3/dist-packages/apt_pkg* /usr/local/lib/python3.7/dist-packages
ln -s ./apt_pkg.cpython-36m-x86_64-linux-gnu.so ./apt_pkg.so
# 注意根据自身情况修改目录和文件名
执行conda指令,似乎不行。执行which python3返回/usr/bin/python3,file指令显示它是个软链接。删除之,用~/.conda/bin/python3代替。再次执行conda指令,之前一大串的traceback应该只剩下了no module named conda这一个错误。尝试重启,进入GNOME,,,,,,,,,果然,还是不行。不过no module named conda变成了no module named conda.cli.pip_warning。
也许不需要删除原来的软链接重建,直接reboot一次也许会有帮助。
尝试gnome-terminal指令
之前早就知道有gnome-terminal指令,可以召唤出另一个GNOME终端。原本以为只能在GNOME下使用,但绝望之下还是尝试了一下在tty2执行这个指令,居然有了新发现:
cannot import _gi from gi
这似乎是错误的真正原因。那么接下来要做的事情很明确了,只要安装gi就好了。
获取gi
按理说,GNOME用户的PC上应该是自动安装gi包的,我尝试apt install后确实如此(但还是建议有问题的话试一下apt install gi --reinstall,也许是遇到了很玄学但也没那么玄学的问题)。那么故伎重施:
find /usr -name "_gi*"
发现这东西在一个gi文件夹里,那么把整个目录复制过来。不过查阅资料发现需要把版本号也改了。
cd /usr/local/lib/python3.7/dist-packages
cp -r /usr/lib/python3/dist-packages/gi .
cd gi
mv _gi.cpython-36m-x86_64-linux-gnu.so _gi.cpython-37m-x86_64-linux-gnu.so
mv _gi_cairo.cpython-36m-x86_64-linux-gnu.so _gi_cairo.cpython-37m-x86_64-linux-gnu.so
# 注意根据自身情况修改目录和文件名
然后登出tty2,从桌面管理器重启。
查看效果
现在按下热键呼出终端,发现成功了,把它重新Add to Favorites。同时发现命令提示符不再是
username@hostname:pwd $
而变成了
(base) username@hostname:pwd $
这是后来安装的miniconda正确运行的标志,不知为啥这个conda.cli.pip_warning的错误就没了。估计Anaconda也能做类似操作。尝试运行了下conda指令,有输出,再也没有烦人的traceback了。但我尝试conda install后发现还有别的错误需要修复。这和gnome-terminal无关,但操作很简单。它会提示某个目录不可写,一般是家目录下一个叫miniconda3的目录,我用
chmod 777 -R ~/miniconda3
把它的权限强行改成了任何人都能操作。再试conda install numpy,成功了。
主要过程总结
本段是对总体上操作流程的总结,免去了笔者试错的过程。但由于笔者主观认为无关的一些东西实际上可能与错误有关,所以上面还是贴出了完整的试错流程,以便在这里的流程总结不可用时作为参考。
- 下文指的“文件名类似”指的是库名相同,例如apt_pkg.cpython-36m-x86_64-linux-gnu.so的库名是apt_pkg。当然,在aarch64机器上需要找aarch64版本的库,一个名叫apt_pkg.cpython-36m-x86_64-linux-gnu.so的库很可能无法在aarch64架构上正确运行。除非用虚拟化技术,但这个需求(指用aarch64虚拟x86_64机器)似乎不常见。
- 一旦发生该问题,gdm3可能很难在图形界面和tty之间切换,经测试lightdm无此问题。不过登录前切到tty也可以。
主要流程:
- 确定你的python版本。有m和没有m对于修复这个错误似乎没有影响。下文记作<pyver>。
- 确定你的有效的python库目录位置,下文记作<libpy-dir>。通常而言,如果对于<pyver>=3.7m,如果存在/usr/local/lib/python3.7,而/usr/lib下存在类似的目录,应该是前者起效。如果<libpy-dir>/dist-packages不存在,那么八成不是正确的路径。
- 确定你的python可执行文件位置。建议reboot后用which指令查看,如果不是conda内部的python可执行文件的话需要重建所有有关的python<版本号>指令的软链接,令它们指向conda提供的可执行文件。(吐槽一下,笔者觉得这么做的鲁棒性不太好,万一别的软件再带一套自己版本的python可执行文件,那岂不是乱套了?不过目前也没别的办法。)注意别把不是软链接的东西删了。
- [可选] 修复apt_pkg找不到的问题。先用apt安装python3-apt,执行conda指令,仍有no module named apt_pkg问题的话再用find指令找到任何名叫apt_pkg.cpython-36m-x86_64-linux-gnu.so或名字类似的文件,有多个则选取版本较新的。这个文件一定能找到,除非之前的apt失败。同一目录下应该还有一个apt_pkg.pyi,一律复制到<libpy-dir>/dist-packages下,并在<libpy-dir>/dist-packages下建立一个指向apt_pkg.cpython-36m-x86_64-linux-gnu.so(可能有差异)的软链接,名为apt_pkg.so。reboot一下,执行conda指令,如果没有报错或报错里没有no module named apt_pkg了的话就是成功了。
- 修复gi。如果在tty下执行gnome-terminal出现cannot import _gi from gi或类似的gi异常的话就可以用本文的方法解决。用find命令找到名字类似_gi.cpython*的东西,应该能找到一个叫gi的目录,如果没有的话用apt安装gi后再试。如果apt成功,一定能找到上文所述的文件和目录。如法炮制,把gi文件夹复制到<libpy-dir>/dist-packages下,找到<libpy-dir>/dist-packages/gi下两个文件名分别类似于_gi.cpython-36m-linux-gnu.so和_gi_cairo.cpython-36m-linux-gnu.so的文件,将文件名中表示版本号的字符串(这里例子中是36m)改为<pyver>对应的字符串,例如<pyver>=3.7m对应37m。
- tty下执行gnome-terminal。正确的话应该会报一个服务器拒绝连接的错误(很显然是指X11服务器),这时切回图形界面并登录应该就可以使用GNOME下的终端了。幸运的话,conda也正常了(但要使用,还需要开放对~/.conda目录的访问权限)。
- [可选] 这个问题一般会导致左侧侧边栏的终端图标消失,热键打开终端后右击选择Add to Favorites就行了。
总之就是python版本太多造成了奇怪的执行路径导致的依赖问题。我用apt,用C++都没这么折腾过