Gentoo配置手记(10/08/07)

Number of View: 218

我又开始折腾了-___,-

1. 不小心删除了Python
按Gentoo handbook折腾了一天把系统安装好了,于是我就决定emerge一下Python,结果把Python3也给装上了。想删除Python3结果直接把Python2.6一并咔嚓了。彼时还没有认识到问题的严重性,结果后来发现emerge命令执行之后完全没反应,问题严重了。翻开Portage Introduction:

Portage is completely written in Python and Bash.

Gentoo的Portage系统是依赖于Python的,so don’t ever unmerge Python completely!
问题解决方法就是重新编译安装Python:

# cd
# tar xzf /usr/portage/distfiles/Python-2.6.5.tgz
# cd Python-2.6.5
# ./configure --with-fpectl --infodir=/usr/share/info/ --mandir=/usr/share/man
# make
# make install prefix=/usr
# rm /usr/bin/python 2>/dev/null
# ln -s /usr/bin/python2 /usr/bin/python

Reference: [Gentoo Forums] I unmerged python… ensuing problems….

2. 无线网卡无法识别
首先确定网卡型号及驱动模块是否已加载:

# lspci | grep Wireless
03:00.0 Network controller: Intel Corporation PRO/Wireless 5100 AGN [Shiloh] Network Connection

搜索该网卡对应的内核模块应为iwlagn,完整的网卡型号与驱动模块对应列表可从 Drivers – Linux Wireless 获得。

# lsmod | grep iwlagn
iwlagn                173410  0
iwlcore               174978  1 iwlagn
mac80211              128158  2 iwlagn,iwlcore
cfg80211              119296  3 iwlagn,iwlcore,mac80211

iwlagn已经正确加载,但是无线网卡仍然无法识别(wlan0: device not found)。
原来还有重要的一步没有做: Software Setup – Installing the microcode files。

# emerge -av net-wireless/iwl5000-ucode

之后无线网卡就可以正确识别了。

Refrence: Iwlwifi — Gentoo Linux Wiki

3. udev更新问题(2010-08-07)
昨天运行了一下emerge -uDN,今早启动系统的时候报错:

* Checking root filesystem...
fsck.ext3: No such file or directory while trying to open /dev/sda6
/dev/sda6:
The superblock could not be read or does not describe a correct ext 2 filessytem.
If the device is valid and it really contains an ext2 filesystem (and not swap or ufs or something else,
then the superblock is corrupt, and you might try running e2fsck with an alternate superblock:
      e2fsck -b 8193  

* Filesystem coudn't be fixed :(

这个问题很好解决,只要利用livecd进入chroot(参见Gentoo handbook),downgrade udev到之前的可用版本就OK了。

# emerge "<=sys-fs/udev-149"

Refrence: [Gentoo Forums] Installing Gentoo

  • Share/Bookmark

给mp3批量嵌入专辑封面

Number of View: 884

鉴于本人素ID3 tag严重洁癖者,之前有用easytag手动给几千个mp3改过tag= = easytag的界面不错,就是不能批量修改,导致那两天改的我手都酸的不行了….入了n1以后有一点不爽的就是不管啥音乐软件,听歌的时候就是抓不到一张封面,那个默认的灰色封面实在让我火大,就用python写了个从豆瓣抓封面图片直接嵌入ID3 tag的程序,一劳永逸了~~

读写ID3 tag信息

对ID3信息的读取和修改依赖了mutagen库,当然用之前还是要对ID3标准有一个基本的了解。

from mutagen.mp3 import MP3
from mutagen.id3 import ID3, APIC, error

audio = MP3(self.filename, ID3=ID3)
try:
    audio.add_tags()
except error:
    pass

有可能音乐文件一开始并没有tag(虽然机率比较小),所以调用add_tags()方法初始化一下,一般情况下都会抛出个error,提示已经有tag了。

album = self.audio['TALB'][0]
frames = self.audio.tags.getall("APIC")
for frame in frames:
    ext = ".img"
    if frame.mime == "image/jpeg" or frame.mime == "image/jpg":
        ext = ".jpg"
    elif frame.mime == "image/png":
        ext = ".png"
    elif frame.mime == "image/gif":
        ext = ".gif"

如果tag中已经包含唱片标题信息,那么audio.keys()的返回结果中就会包含”TALB”这一项,其他还有比如”TLE1″(表演者),“TCON”(流派)等等。ID3标准中规定代表唱片封面信息的帧结构如下:

audio.tags.add(APIC(encoding = 3,mime = "image/jpeg",type = 3,
desc = u'Cover',data=imagedata))
audio.save()

encoding = 3表示utf8编码,mime可以为”image/jpeg”(“image/jpg”)或者”image/png”格式,type=3表示写入的是front cover,desc是描述信息,data是图片的二进制数据,可以从某个uri读取,也可以从本地读取。

从豆瓣抓取封面图片

豆瓣很早就开始提供各种API了,抓取过程很简单,默认是atom,把得到的xml用minidom库解析一下就可以得到封面图片的url了,这个不多说了。

req = urllib2.Request(self.site_url+"?"+url_data)
response = urllib2.urlopen(req)
result_xml = response.read()

elements = minidom.parseString(result)
albums = []
for entry in elements.getElementsByTagName("entry"):
    album = {}
    try:
        album["id"] = self.getText(entry.getElementsByTagName("id")[0].childNodes)
        album["title"] = self.getText(entry.getElementsByTagName("title")[0].childNodes)
        album["author"] = self.get_authors(entry.getElementsByTagName("author")     [0].getElementsByTagName("name"))
        album["image"] = self.get_image(entry.getElementsByTagName("link"))
        albums.append(album)
    except IndexError:
        pass

这个时候得到的图片的url一般是”http://t.douban.com/spic/s*.jpg”的格式,这些图片都比较小分辨率比较低,一般一张2,3k左右。我需要清晰一些,大一些的图片,所以把url中spic换成了lpic,这时得到的图片在20k左右。

image_url.replace("spic","lpic",1)

代码

源码见这里
必需的命令行参数为-d,后接要处理的目录路径。-r表示递归处理该目录下所有子目录下的所有mp3文件,否则默认只处理指定目录下的文件。

成果

我的音乐目录是~/Music,执行python cmd.py -r -d ~/Music递归为该目录下所有mp3文件自动嵌入封面,由于mp3 tag有的有残缺,成功率大约在90%以上。
Amarok播放效果图:
2010-05-15-105026_671x276_scrot
Android Music播放效果图:
snap20100515_113833

  • Share/Bookmark

List performance: Python vs Java

Number of View: 514

这篇post的主要由来是某次算法作业误用Python做了无用功,性能完全达不到要求,后来换用Java才搞定。作业是一个经典的算法问题:求最近点对,要求的输入数量级达到百万。Java做出来的结果大约是5秒左右,Python的话就完全废了,原因是其中涉及到庞大的list的new操作。

Python list VS Java array

首先做一个简单的实验,分别计算用Python和Java新建一个list的时间。

Python代码:

li = []
for i in range(size):
    li.append(0)

Java代码:

int[] li = new int[size];

结果对比如下:

sizePython(ms)Java(ms)
100.0120.002
1000.0450.002
10000.3470.005
100004.0110.034
10000034.5410.304
1000000353.4203.749

二者的时间复杂度都是O(n),但在常数上相差两个数量级。究其原因,
The time needed to append an item to the list is “amortized constant”; whenever the list needs to allocate more memory, it allocates room for a few items more than it actually needs, to avoid having to reallocate on each call (this assumes that the memory allocator is fast; for huge lists, the allocation overhead may push the behaviour towards O(n*n)).
也就是说,Python中list的append操作仅当空间不够时才另分配一块新的空间,根据平摊分析(Amortized Analysis)原理,创建一个长度为n的list的时间为c*n(c为平摊常数)。而Java的数组的new操作是一次分配一整快空间,这就不难解释为何两者的性能差异如此之大了。

For loop vs List comprehension

实际上,Python提供了另一种更快地创建list的方法:List Comprehension。List comprehensions run a bit faster than equivalent for-loops (unless you’re just going to throw away the result).

li = [ 0 for i in range(size) ]
sizeappend(ms)list comprehension(ms)
100.0120.009
1000.0450.026
10000.3470.214
100004.0112.228
10000034.54121.701
1000000353.420221.127

Python list vs Java Vector

Python的list与Java的Vector有些类似,再做一个对比:

Vector list = new Vector();
for(int i=0;i<size;i++)
    list.add(i)

sizePython list(ms)Java Vector(ms)
100.0120.741
1000.0450.778
10000.3471.1108
100004.0113.6601
10000034.54121.008
1000000353.42081.820

在默认构造函数中,Vector的初始存储能力是10个元素,如果新元素加入时存储能力不足,则以后存储能力每次加倍。每次扩展存储能力时,所有现有的元素都要复制到新的存储空间之中。add操作有可能做了额外的优化,因为时间复杂度曲线并非纯线性的。

总之,在注重性能并需要多次创建较大的list的应用中,Python并不适用。

注:实验环境:
软件:Archlinux(Kernel2.6.32)+Python2.6.4
硬件:CPU 2Ghz*2,RAM 2GB

Refrence:
1. An Introduction to Python Lists
2. PythonSpeed/PerformanceTips

  • Share/Bookmark