这不是一篇关于编程的文章,是从运行的条件来考虑整个软件的分析。anaconda是90%的python代码,那么它所运行的python环境和库到底有那些?import了些什么?这对于安装程序的瘦身是很重要的,也是对认识整个系统环境迈出的第一步!
我不会去急着去看源代码,首先我会去找一个可运行的环境中寻找整个运行流程:
(以下操作均基于asianux3.0)
将第一张光盘中的/image/stage2.img,
下载到本地。
#file
stage2.img
stage2.img:
Squashfs filesystem, little endian, version 3.0, 68102631 bytes, 4938
inodes, blocksize: 65536 bytes, created: Wed Aug 29 16:58:29 2007
#mkdir
stage2
#mount
-t squashfs -o loop stage2.img stage2
这就是我们通常看到的整个启动安装的全部程序、配置文件、库文件等
有了这个stage2之后,正如题目所言,此文仅考虑运行anaconda的python环境问题,其它一概不论,在下篇文章我会提到anaconda的启动过程,诸如stage1\stage2\anaconda\rpminstall等等。
#cd stage2
此时可以看到类似我们完成系统的根目录的目录。
$ ls
etc lib modules proc usr var
如果你在系统安装的过程中在终端下执行过命令的话,就明白那里的环境变量指的是什么地方了。
我到/usr/bin/下查看anaconda的主程序。当然此anaconda可执行,就代表在此之前的环境变量就设置好了。请参阅后续文章。
在python程序中,先找__main__,类似于c中main,如下:
if __name__ == "__main__":
anaconda = Anaconda()
setupPythonPath()
......
setupPythonUpdates()
.......
Anaconda是一个类,在整个程序中有很多地方继承,具体的分析将在以后慢慢的进行,略过这句,看此文的核心内容:
setupPythonPath(),这是一个函数,具体代码如下:
def setupPythonPath():
# For anaconda in test mode
if (os.path.exists('isys')):
sys.path.append('isys')
sys.path.append('textw')
sys.path.append('iw')
else:
sys.path.append('/usr/lib/anaconda')
sys.path.append('/usr/lib/anaconda/textw')
sys.path.append('/usr/lib/anaconda/iw')
if (os.path.exists('booty')):
sys.path.append('booty')
sys.path.append('booty/edd')
else:
sys.path.append('/usr/lib/booty')
sys.path.append('/usr/share/system-config-date')
isys,textw,iw分别为检查系统的程序、运行在text模式下的screen,运行在图形模式时的UI界面。
booty是"""Module for manipulation and creation of boot loader configurations"""
最后添加的变量是设置系统时间的python程序。
setupPythonUpdates(),这是真正的主角。代码如下:
def setupPythonUpdates():
import glob
#导入glob模块,glob对于熟悉shell的人来说,应该不陌生。
# get the python version. first of /usr/lib/python*, strip off the
# first 15 chars
pyvers = glob.glob("/usr/lib/python*")
pyver = pyvers[0][15:]
#利用glog定义python的版本号变量。
try:
os.mkdir("/tmp/updates")
except:
pass
for pypkg in ("rhpl", "yum", "rpmUtils", "urlgrabber", "pykickstart",
"rhpxl", "pirut"):
if os.access("/mnt/source/RHupdates/%s" %(pypkg,), os.X_OK):
try:
os.mkdir("/tmp/updates/%s" %(pypkg,))
except:
pass
#建立rhpl,yum,rpmUtils等目录在stage2运行环境的/tmp/updates目录,
# symlink the existing ones
for f in os.listdir("/mnt/source/RHupdates/%s" %(pypkg,)):
os.symlink("/mnt/source/RHupdates/%s/%s" %(pypkg, f),
"/tmp/updates/%s/%s" %(pypkg, f))
# get the libdir. *sigh*
if os.access("/usr/lib64/python%s/site-packages/%s" %(pyver, pypkg),
os.X_OK):
libdir = "lib64"
elif os.access("/usr/lib/python%s/site-packages/%s" %(pyver, pypkg),
os.X_OK):
libdir = "lib"
else:
# If the directory doesn't exist, there's nothing to link over.
# This happens if we forgot to include one of the above packages
# in the image, for instance.
continue
if os.access("/tmp/updates/%s" %(pypkg,), os.X_OK):
for f in os.listdir("/usr/%s/python%s/site-packages/%s" %(libdir,
pyver,
pypkg)):
if os.access("/tmp/updates/%s/%s" %(pypkg, f), os.R_OK):
continue
elif (f.endswith(".pyc") and
os.access("/tmp/updates/%s/%s" %(pypkg, f[:-1]),os.R_OK)):
# dont copy .pyc files we are replacing with updates
continue
else:
os.symlink("/usr/%s/python%s/site-packages/%s/%s" %(libdir,
pyver,
pypkg,
f),
"/tmp/updates/%s/%s" %(pypkg, f))
"rhpl",
"yum", "rpmUtils", "urlgrabber", "pykickstart","rhpxl",
"pirut"这几个库是python库的第三方的,也就说是python默认不会自动安装的。当然上述的python模块都可以在
/usr/lib/python2.4/site-packages中找到。注意此函数对os模块的调用很频繁。这对于linux系统编程来说,这是家常
便饭。
os.access,判断文件是否存在,若存在,则返回真。
进入phthon交互式模式,执行如下内容:
import os
dir(os)
os.__doc__看简单的查看os模块的功用。