python移植到arm的单板
python移植到arm的单板
注:下文的CSU是我们一个嵌入式单板的名称。
1 前言
作者的话:
本人非常喜欢 python ,一直梦想可以移植到
CSU
中。但是
python
诞生之初并没有想到要应用在嵌入式领域,因此,
python
的交叉编译比较复杂。
python
的交叉编译花费了我一些时间进行摸索,这篇文章是在查阅了
N
多资料,进行了
N
多尝试后成功的,就在想彻底放弃的时候,
NEVER GIVE UP
的信念让我进行前进,而恰恰是这前进的一步,转暗为明,相继研究出来
CSU
的
NFS
与
CSU
的
Python
!这是让自己非常振奋的!
2 交叉编译
这里以 python2.7.6 进行陈述。
下载 python 的
linux
版本源码包,解压到
/opt
中。
2.1 更新虚拟机上的 python 版本
为了最大的稳定性,建议更新虚拟机上的版本与交叉编译的版本一致。由于下载的源码包版本肯定是最新的,因此,顺便更新一下虚拟机的 python 版本也是一件好事。
传统三部曲。
./configure
make
make install
2.2 配置 arm 的 configure
由于源码包需要生成 pc 版的
python
和
arm
版的
python
,因此,需要隔离开,这个非常关键。
pc 版采用原有路径,不改变。
arm 则在源码包下
mkdir arm_build
由于 configure 会在当前目录下生成
Makefile
等文件,因此,不能在源码包下直接
configure
,必须在
arm_build
里执行。这点非常重要。
cd arm_build
由于交叉编译中,需要明确如下两个变量的值,因此,这里必须人工定义。 ptmx 就是虚拟串口的意思,由于我的单板以后要用到这个,因此,设为
yes
。
设为 no 一样是可以的。
echo ac_cv_file__dev_ptmx=yes > config.site
echo ac_cv_file__dev_ptc=yes » config.site
export CONFIG_SITE=config.site
建好 arm 版
python
要安装到的文件夹。
arm_install=/opt/arm_python
mkdir $arm_install
configure 如下:
../configure –host=arm-none-linux-gnueabi –build=i686-linux-gnu –target=arm-none-linux-gnueabi –disable-ipv6 –prefix=$arm_install –enable-shared –silent
其中, arm 的
gcc
采用
2011
版本;
由于 ipv6 支持有问题,因此,必须关闭;
–silent 去掉
configure
过程中的垃圾信息,只输出
warning
及以上的关键信息,我特别喜欢这个。
–build 是必须填的,怎么知道这个
build
信息呢,最简单的方法就是
gcc –v
里面会有 gcc 的
configure
信息,里面就有
–build
的信息,复制过来就万无一失。
–target 其实可以不写,系统可以猜出来的,但这里还是写上。
2.3 pgen 准备
这个非常关键。
在 configure 之后
make
或
make Parsr/pgen
。
可以在 arm_build 的
Parser
文件夹里发现
pgen
这个执行文件,它是
python
的语法分析器之类东西,但问题来了。
这个东西是不能用的,因为是交叉编译版本的 pgen ,在虚拟机下用不了。
最简单的解决方法如下:
回到源码包路径
cd ../
生成 pc 版本的
pgen
make Parser/pgen
复制到 arm_build 的
Parser
里面
cd arm_build
cp ../Parser/pgen Parser
下面这一步非常关键而且非常巧妙
touch –t 12312359 Parser/pgen
意思是:将 pgen 文件的日期改为今年的最后一分钟生成的。
为什么需要这一步?
很简单:
因为, arm 版
python
在
make
时,会生成它的
pgen
,就会把刚才复制过来的给替换掉了,改了未来的时间,就会忽略跳过,非常巧妙的技巧!
2.4 make && make install
现在可以 make (或
make python
)了。
我喜欢加上 –silent ,这样可以减少很多垃圾信息。
make 完成后,注意:
这里,使用 make install 一般会出错,显示缺失
_struct
的类型错误。
使用 make -i install 才能搞定。
-i 就是 ignore 错误的意思,继续前进。这里可能的问题是:前面需要某模块,但是
install
中却在后面才安装这个模块,导致了前面找不到模块的错误,其实,整个完成后,是完整的。
这一招对这种时序问题,或 install 中出现的时序问题比较难解决时,能帮上大忙。
现在,查看 /opt/arm_python 这个安装目录,可以发现已经有相关
python
文件了。
3 第三方库
python 容易使用的一大特点就是自由开放的库很多,官方不可能全部纳入自己的标准库中,因此,安装自己需要的第三方库是必要的。
举例:
这里安装第三方 xlrd 库,这个库可以非常方便的读取
excel
文件的内容,即使不在
windows
下,即使没有安装
excel
,也可以,而且速度非常的快。
下载源码包后解压, cd 到那个路径下。
python setup.py install
就可以完成第三方库的安装了。这里的 install 其实就是包括
build
和
install
。
对于虚拟机,会安装到
/usr/local/lib/python3.3/site-packages
第三方库基本默认安装在 site-packages 里。
那如何安装到我们的 arm 的
python
里呢。
很简单:
python setup.py install –prefix=/opt/arm_python
( 默认情况下,这个前缀为
/usr/local/)
如果没有正确安装,当程序需要这个库时,会报找不到模块的 error 。
4 应用
由于 python 的库文件很大,直接拷贝到
CSU
是不现实的。裁剪库也很麻烦,而且消弱了功能。因此,这里采用
NFS
。
python
的
bin
、
lib
等文件,以及自己编写的代码文件都放在虚拟机上。
CSU
通过
NFS
使用
python
即可。
CSU 侧:
mkdir /mnt/python
mount –o nolock 10.9.102.23:/opt/arm_python /mnt/python
在 /etc/profile 里
在 export PATH 一行后面加入
:/mnt/python/bin
在 export LD_LIBRARY_PATH 一行后面加入
:/mnt/python/lib
这样就可以使用 python 了。
python –V 就可以看到
python
的版本信息了。
python 回车后
就可以进入 python 的
shell
了,可以在命令中输入
python
语句。
由于这个 CSU 上的
python
的
shell
非常不好用,打错字无法修正,⊙﹏⊙
b
汗,因此,我一般都在虚拟机上写代码,
CSU
上运行就行了。(注,
python
的
shell
退出方式是输入
exit()
指令)
例如:
mkdir /opt/arm_python/code
在 code 写入
helloworld.py
的文件
在 CSU 中:
python /mnt/python/code/helloworld.py
就可以看到输出了。
5 python3 的移植
同 python2 。
虚拟机是支持同时安装两个版本的 python 的,它们的路径会通过版本号进行区分。
arm 版的
python
也一样,在
/opt/arm_python
会进行版本的区分。
默认 python 链接指向
python2
,如果需要更改,
rm
后
ln
到
python3
即可。
6 懒人时刻
又是将书变薄的时候了,以下是精华,即自动化交叉编译脚本。
#prepare
echo "prepare stage"
arm_install=/opt/arm_python
arm_build=`pwd`/arm_build
mkdir $arm_build
mkdir $arm_install
cd `pwd`
#arm comfigure
echo "arm confiure stage"
cd $arm_build
echo ac_cv_file__dev_ptmx=yes > config.site
echo ac_cv_file__dev_ptc=yes >> config.site
export CONFIG_SITE=config.site
../configure --host=arm-none-linux-gnueabi --build=i686-linux-gnu --target=arm-none-linux-gnueabi --disable-ipv6 --prefix=$arm_install --enable-shared --silent
#pc pgen
echo "pc pgen stage"
cd -
./configure --silent
for args in $@
do
if [ $args = "all" ];then
make --silent && make install --silent
break
fi
done
make Parser/pgen --silent
cd -
cp ../Parser/pgen Parser
#change the pgen time,
# or else the cross compile will replace this pc version pgen. important!!
touch -t 12312359 Parser/pgen
#make
echo "make stage"
make python --silent && make -i install
#make it smaller
#arm-none-linux-gnueabi-strip -s $arm_install/bin/python3.3
exit 0
使用方法:
chmod +x arm_python
复制到源码包路径下(或 ln 到源码包路径下);
执行 ./arm_python 即可。
默认安装在 /opt/arm_python 里。
(当加入参数 all 时,脚本会顺便更新虚拟机上的
python
)
7 附录(性能测评)
7.1 不同 cpu 与系统的对比
执行如下测评语句:
import time
start_time=time.clock()
for i in range(1000):
print(‘good’)
end_time = time.clock()
print(’total time is ‘, end_time-start_time)
结果对比:
CPU | OS | Time |
奔腾 E6700 (酷睿 core2 ) | Windows7 | 0.03s |
奔腾 E6700 (酷睿 core2 ) | Virtual Ubuntu | 0.01s |
AMD 炫龙双核 | Ubuntu | 0.003s |
AT9260 ( Arm9 ) | Linux | 0.6s |
AM335 ( A8) | Linux | 0.18s |
结果在我的预测范围里,即 CSU 的处理能力只有主流台式
2
核
cpu
的几百分之一,属于可以接受的范围。
(有趣的是, ubuntu 的执行速度远高于
windows
!
python
虽然是跨平台语言,但是在
linux
环境下,却有明显的优势)
另一个将数据字典自动转为 XML 的程序对比:
win7:0.35s
A8:8s
7.2 python 与 C 的对比
执行 1000 次相加与输出:
C 语言代码如下:
1 #include <stdio.h>
2 #include <sys/time.h>
3 void main(void){
4 struct timeval start,end;
5 gettimeofday(&start,NULL);
6 int i,sum=0;
7 for(i=0;i<1000;++i){
8 sum+=i;
9 printf("%d\n",sum);
10 }
11 gettimeofday(&end,NULL);
12 printf(“total time is %d\n”,1000000*(end.tv_sec-start.tv_sec)+end.tv _usec-start.tv_usec);}
Python 代码如下:
1 import time
2 start_time = time.clock()
3 sum=0
4 for i in range(1000):
5 sum=i+sum
6 print(sum)
7 end_time = time.clock()
8 print(’time is ‘,end_time-start_time )
C 一共使用:
34
毫秒;
Python 一共使用:
180
毫秒。
Python 为
C
速度的
20%
左右,属于可以接受的范围内。