Ubuntu开机自启动python程序中相关库导入失败,例如Tensorflow与rospy解决方案(rc.local)

Ubuntu开机自启动本身一个程序不是一个难事。本文要解决的不是这个问题,而是针对于python程序可以开机自启动,而其中的Tensorflow与rospy无法正常导入的问题。

事情是这样的,机器人中有一个程序是基于Tensorflow的,为了避免每次都需要ssh进去远程打开程序,领导要求把它做成开机自启动的形式。于是我决定通过把脚本写进/etc/rc.local方式,让机器人开机自启动这个程序。

然而,开机后通过ps|aux grep 指令却没能在后台发现我启动的程序进程号。

于是测试了多台电脑,包括PC上的Ubuntu18.04,Xavier上的Ubuntu,均发现不能自启动。

先放一个正常自启动的方式:

Ubuntu 18.04 程序设置开机自启动

实际上经过上述博客中的方法,已经可以把普通的Python程序自启动起来了,但包含了tensorflow或者rospy的库的程序无法正常启动。经过排查,发现主要是两个地方出问题:

import rospy

import tensorflow

这两个库没能导入。

排查方法:先在/etc/rc.local中写入如下脚本:

#! /bin/bash
python /home/zhaokai/test.py >/home/zhaokai/1.txt 2> /home/zhaokai/stderr.txt
exit 0

意为把输出记录到home下的1.txt中,把报错记录home下的stderr.txt中。这样才能方便查看是否启动,进行到了哪一步,有哪些报错输出。

然后在home下创建一个测试程序test.py:

import numpy
print("numpy start")

import rospy
print("rospy start.")

import tensorflow
print("tensorflow start")

重启后发现,在1.txt中,只有numpy start 这一句输出。并没有看到rospy start 和tensorflow start这两句话。

打开stderr.txt,看到报错输出为:

Module compiled against API version 0xa but this version of numpy is 0x9
Module compiled against API version 0xa but this version of numpy is 0x9
Traceback (most recent call last):
  File "<stdin>", line 4, in <module>
ImportError: No module named rospy

同样,如果在test.py中把tensorflow放在前面,重启电脑后会发现,报错为:

Module compiled against API version 0xa but this version of numpy is 0x9
Module compiled against API version 0xa but this version of numpy is 0x9
Traceback (most recent call last):
  File "<stdin>", line 4, in <module>
ImportError: No module named tensorflow

难道是电脑没有装环境?

于是开机后打开终端,输入python,在其中import tensorflow 以及rospy,可以正常导入。

于是修改test.py:

import sys
print(sys.path)

import numpy
print("numpy path:")
print(numpy.__path__)
print("numpy start")

import rospy
print("rospy start.")
print("rospy path:")
print(rospy.__path__)


import tensorflow
print("tensorflow start")
print("tensorflow path:")
print(tensorflow.__path__)

再次重启,打开输出1.txt,发现输出为:

['/home/zhaokai', '/usr/lib/python2.7', '/usr/lib/python2.7/plat-x86_64-linux-gnu', '/usr/lib/python2.7/lib-tk', '/usr/lib/python2.7/lib-old', '/usr/lib/python2.7/lib-dynload', '/usr/local/lib/python2.7/dist-packages', '/usr/lib/python2.7/dist-packages', '/usr/lib/python2.7/dist-packages/wx-3.0-gtk3']

numpy path:
['/usr/lib/python2.7/dist-packages/numpy']
numpy start

似乎破案了。

重新在开机后的程序里打开终端,输入python,然后执行同样的代码,结果却不相同:

['/home/zhaokai', '/home/zhaokai/turtlebot3_ws/devel/lib/python2.7/dist-packages', '/home/zhaokai/cat_ws/install_isolated/lib/python2.7/dist-packages', '/opt/ros/melodic/lib/python2.7/dist-packages', '/usr/lib/python2.7', '/usr/lib/python2.7/plat-x86_64-linux-gnu', '/usr/lib/python2.7/lib-tk', '/usr/lib/python2.7/lib-old', '/usr/lib/python2.7/lib-dynload', '/home/zhaokai/.local/lib/python2.7/site-packages', '/usr/local/lib/python2.7/dist-packages', '/usr/lib/python2.7/dist-packages', '/usr/lib/python2.7/dist-packages/wx-3.0-gtk3']
numpy path:
['/home/zhaokai/.local/lib/python2.7/site-packages/numpy']
numpy start
rospy start.
rospy path:
['/opt/ros/melodic/lib/python2.7/dist-packages/rospy']
tensorflow start
tensorflow path:
['/home/zhaokai/.local/lib/python2.7/site-packages/tensorflow/python/keras/api/_v1', '/home/zhaokai/.local/lib/python2.7/site-packages/tensorflow_estimator/python/estimator/api/_v1', '/home/zhaokai/.local/lib/python2.7/site-packages/tensorflow', '/home/zhaokai/.local/lib/python2.7/site-packages/tensorflow/_api/v1']

从这二者对比,我们可以得到两点信息:

1.在开机启动的python程序中,sys下的path默认并不会像终端中一样加入'/home/zhaokai/.local/lib/python2.7/site-packages',以及'/opt/ros/melodic/lib/python2.7/dist-packages'两个路径。而恰好tensorflow和rospy的库就位于这两个路径下。此外平时写在bashrc下的source路径也不会在开机启动的程序中被导入。

2.开机启动的numpy是来源于'/usr/lib/python2.7/dist-packages/numpy',而自己在终端中运行的python中的numpy路径来源于'/home/zhaokai/.local/lib/python2.7/site-packages',这就解释了为什么可以启动numpy,而不能导入tensorflow以及rospy。另外报错中的Module compiled against API version 0xa but this version of numpy is 0x9应该也是由此导致,应该是系统自带的numpy版本太低了。

于是我们把test.py的代码再次改为:

import sys
sys.path.append('/home/zhaokai/.local/lib/python2.7/site-packages')
sys.path.append('/opt/ros/melodic/lib/python2.7/dist-packages')

import numpy
print("numpy path:")
print(numpy.__path__)
print("numpy start")

import rospy
print("rospy start.")

import tensorflow
print("tensorflow start")

这次运行后发现,1.txt中的输出为:

['/home/zhaokai', '/opt/ros/melodic/lib/python2.7/dist-packages', '/usr/lib/python2.7', '/usr/lib/python2.7/plat-x86_64-linux-gnu', '/usr/lib/python2.7/lib-tk', '/usr/lib/python2.7/lib-old', '/usr/lib/python2.7/lib-dynload', '/home/zhaokai/.local/lib/python2.7/site-packages', '/usr/local/lib/python2.7/dist-packages', '/usr/lib/python2.7/dist-packages', '/usr/lib/python2.7/dist-packages/wx-3.0-gtk3']
numpy path:
['/usr/local/lib/python2.7/dist-packages/numpy']
numpy start
rospy start.

发现rospy可以启动了,但是tensorflow却依旧没能启动。

打开记录报错信息的stderr.txt文件,这次发现不再说找不到tensorflow了,而是换了一个报错输出:

Module compiled against API version 0xa but this version of numpy is 0x9
Module compiled against API version 0xa but this version of numpy is 0x9
from google.protobuf import descriptor as _descriptor
ImportError: No module named google.protobuf

难道google.protobuf的路径没能加进去?

重新在启动后的电脑里输入import google.protobuf,完全可以导入。打印其路径,显示为:

['/home/zhaokai/.local/lib/python2.7/site-packages/google/protobuf']

然而/home/zhaokai/.local/lib/python2.7/site-packages这个路径已经被加入到开机启动的sys中了,这是见鬼了?

经过一番踩坑,终于歪打正着发现一个解决方案:

进入到/home/zhaokai/.local/lib/python2.7/site-packages/google下,创建一个空文件:

touch __init__.py

再重启电脑,打开1.txt:

['/home/zhaokai', '/opt/ros/melodic/lib/python2.7/dist-packages', '/usr/lib/python2.7', '/usr/lib/python2.7/plat-x86_64-linux-gnu', '/usr/lib/python2.7/lib-tk', '/usr/lib/python2.7/lib-old', '/usr/lib/python2.7/lib-dynload', '/home/zhaokai/.local/lib/python2.7/site-packages', '/usr/local/lib/python2.7/dist-packages', '/usr/lib/python2.7/dist-packages', '/usr/lib/python2.7/dist-packages/wx-3.0-gtk3']
numpy path:
['/usr/local/lib/python2.7/dist-packages/numpy']
numpy start
rospy start.
tensorflow start

说明tensorflow被正常导入了。

打开stderr.txt,发现这次不会报找不到库的错误了,而是只剩下:

Module compiled against API version 0xa but this version of numpy is 0x9
Module compiled against API version 0xa but this version of numpy is 0x9

根据1.txt和stderr.txt的信息,我们可以得到,当['/usr/local/lib/python2.7/dist-packages/numpy']和['/home/zhaokai/.local/lib/python2.7/site-packages/numpy']同时存在时,rc.local中的python程序会优先导入系统路径下自带的numpy包。

系统自带的numpy包版本太低了,numpy是很多包的基础,包括tensorflow。如果这个问题置之不理,虽然可以正常导入tensorflow,但是很多相关的库中的一些高级功能则会因为numpy版本太低,而无法使用甚至报错

那么能不能更新系统numpy包的版本呢?尝试用pip update等命令来升级,却发现升来升去都只能升级位于'/home/zhaokai/.local/lib/python2.7/site-packages'下的numpy,动不了系统下的numpy分毫。

 

于是,我想如果在代码中,手动把sys.path中的['/usr/local/lib/python2.7/dist-packages']给删掉呢?这样是不是就不冲突了?

但是这样导致rospy又不能正常启动了,提示找不到别的东西。

 

吐了呀。这个问题纠缠了我好久,最后我失去了耐心,不再尝试对系统自带的numpy进行升级,而是干脆直接进入到/usr/local/lib/python2.7/dist-packages这个文件夹下,把numpy这个文件夹给重命名成了numpy2(其实删掉也行)。

让你找不到系统路径下的numpy,行不行?

 

重启后发现,stderr.txt中没有报错信息了,而1.txt中的numpy路径也换成了高级版本的numpy路径。

测试完成,替换成自己的代码,机器人开机,一切ok~

如果你也遇到了这个问题,但是情况和我的又有点区别,比如你的用户名不叫zhaokai(哈哈),或者你的tensorflow是用anaconda装的,那也可以按我的思路来走,排查一遍,解决自启动失败的问题。

如果帮到你请点个赞吧~

评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值