安装 scipy
昨晚装 scipy,用 pip 装花了一个多小时,结果装完一 import scipy.fftpack
,居然报不存在。
好吧,太娇气了,只能试别的操作了。
先吃后悔药:sudo pip uninstall numpy scipy
其实我们没必要用最新版本,所以先试试 apt-get,不行再从源代码编译呗。
sudo apt-get install libopenblas-base libatlas3-base update-alternatives --list libblas.so.3 sudo apt-get install python-numpy python-scipy --reinstall
速度很快,就搞定了。但怎么检查有没有用上 BLAS 啥的呢?Stack Overflow 有网友说可以看动态库关联,他给的语句可能得改改,因为路径文件名啥的可能真的不一样,我折腾到最后用的是:
$ ldd /usr/lib/python2.7/dist-packages/numpy/core/multiarray.arm* linux-vdso.so.1 (0x7ea74000) /usr/lib/arm-linux-gnueabihf/libarmmem.so (0x76e32000) libblas.so.3 => /usr/lib/libblas.so.3 (0x76dca000) libm.so.6 => /lib/arm-linux-gnueabihf/libm.so.6 (0x76d4b000) libpthread.so.0 => /lib/arm-linux-gnueabihf/libpthread.so.0 (0x76d22000) libc.so.6 => /lib/arm-linux-gnueabihf/libc.so.6 (0x76be3000) /lib/ld-linux-armhf.so.3 (0x76f99000) libopenblas.so.0 => /usr/lib/libopenblas.so.0 (0x76453000) libgfortran.so.3 => /usr/lib/arm-linux-gnueabihf/libgfortran.so.3 (0x7639e000) libgcc_s.so.1 => /lib/arm-linux-gnueabihf/libgcc_s.so.1 (0x76371000)
所以算是有的了。再试试 import scipy.fftpack
,也正常,那就完事了。
回过头来再跑程序,逐步解决了如下问题:
- 诶怎么 matplotlib 没了?那就再来:
sudo apt-get install python-matplotlib
(其实最早我试的 pip 安装pip install -U matplotlib -i https://pypi.mirrors.ustc.edu.cn/simple
,然后我就看到 pip 默默地又把我卸掉的 numpy 装回来了……于是它编译的时候我就迅速 Ctrl+C 了) - 接着报没装 skimage,那就:
sudo apt-get install python-skimage
- 继续
sudo pip install loky -i https://pypi.mirrors.ustc.edu.cn/simple
终于,能运行了。
设置自启动
差点忘记设置服务器自启动了。之前弄这个有好多坑,反正到最后翻了好多网上的做法,我的选择简单粗暴(先感谢 AskUbuntu ):
sudo nano /etc/rc.local
# 增加以下内容,注意 rc.local 运行的时候就是 root 权限的 exec 2> /tmp/rc.local.log # send stderr from rc.local to a log file exec 1>&2 # send stdout to the same log file set -x # tell sh to display commands before execution python /home/pi/IPBroadcaster.py & python /home/pi/cubik/server/server.py & # echo `date +%Y-%b-%d_%H:%M:%S` > /tmp/ran_rc_local # check that rc.local ran exit 0
回头解决代码问题
距离我还在埋头处理线程问题,已经经过了两天。终于我可以好好调试这个鬼问题了。
在这个项目里,线程安排是这个样子的:
- 主进程运行过程中需要处理信号和 socket,而我们有一个运行时间很长的 taskInstance 线程,它按需开始结束,没有对主进程的环境依赖(准确来说,它有可能收到强退信号,但这个信号不能让主进程也强退了),需要有 Pipe 与主进程通信
- taskInstance 线程运行过程中有一个 multiprocessing pool,同时运行几个 CPU 占用较多的 Python 任务(姑且叫做 visualSubtask 吧,反正里面东西不是我写的),输入输出需要能方便地传 Python 的数据类型,运行过程中最多就是 print 一些调试信息,倒不需要中途用 Pipe 传数据;同样,它有可能收到强退信号,但这个信号不能影响主进程强退
之前我是想试图解决信号的问题。实际上因为大部分的 forking 都是在加载完服务器程序之后进行的,所以对子进程发出的所有信号总会被服务器的信号处理代码截获,于是会导致主程序重启。
一种解决方案是在服务器程序加载之前做 prefork,把 taskInstance 的 process 先创建了。然而因为 taskInstance 是按需开始结束的,这样对它内部运行的改动还是挺大的(不过这部分代码是我写的,也不算麻烦,它也不会有长时间计算,轮询接收外头信号还是很容易,就是流程时序要求比较高)。更大的问题是,如果 taskInstance 意外停止了,之后要初始化它的那个“纯净”的环境就有点困难了。后面的路走不通的话,就还是得乖乖这么做了。
在逛 StackOverflow 的过程中看到有人推销自己写的 loky 库,似乎可以实现在程序运行中途 fork 一个纯净环境出来(Reusable executor)。两天前的中午我试了下,结果报错 Cannot pickle connection object. This object can only be passed when spawning a new process
(传 Pipe 进子程序是我们程序必须要做的)。于是就得查查怎么把 connection object pass in before spawning a new process 咯。然而这库文档真的少得不行,只能仔细再研究看看了。
尝试许久,发现几个问题:
- 自己的 Pipe 传不进去。用事先在主线程定义好,子线程 global,得到的 Pipe 是坏的(查了下,说是升级到 Python 3+ 就好了,然而代码还有别人写的部分,懒得升级);说用 initializer 的 initargs 传进去,我硬是自己拿 loky 的 context 出来,把里面 Manager 的生成语句改了,加上自己的 initializer,再传给 get_reusable_executor 去用,结果啥都没收到,initializer 也没 print 东西出来。(感觉这个 Manager 程序根本没用到吧,放弃。)
- 会有 defunct 进程,感觉这个是 BUG。啥都没干只 get_reusable_executor 一次,结果 cherrypy 会根据代码更新自动重启,重启的时候
/usr/bin/python -c from loky.backend.semaphore_tracker import main; main(3)
这个进程似乎是没处理好,就 defunct 了,Ctrl+C 的时候倒是这些进程就消失了。
所以,还是得改成提前创建 taskInstance 的进程的方式,这时候我倒是觉得可以参考 http://www.defuze.org/archives/198-managing-your-process-with-the-cherrypy-bus.html 里 Broker 工作的方式重写下程序啦。
P.S. 送一条 OpenCV 3 + Python 3 的指令 cmake -D CMAKE_BUILD_TYPE=RELEASE -D CMAKE_INSTALL_PREFIX=/usr/local -D INSTALL_C_EXAMPLES=OFF -D INSTALL_PYTHON_EXAMPLES=OFF -D OPENCV_EXTRA_MODULES_PATH=~/opencv_contrib/modules -D WITH_TBB=ON -D BUILD_TBB=ON -D WITH_OPENMP=ON -D BUILD_EXAMPLES=OFF -D WITH_NVCUVID=ON -D WITH_CUDA=ON -D BUILD_DOCS=OFF -D BUILD_PERF_TESTS=OFF -D BUILD_TESTS=OFF -D WITH_OPENCL=ON -D PYTHON_EXECUTABLE=$HOME/.virtualenvs/cv/bin/python3.5 -D PYTHON3_NUMPY_INCLUDE_DIRS=$HOME/.virtualenvs/cv/lib/python3.5/site-packages/numpy/core/include ..