LINUXQQ

十一月 30, 2010

python 字典函数

Filed under: python — admin @ 10:01 下午

用的时候总是找不到 于是乎从网上转载过来吧 免的老去到处搜索

  • D.keys() #返回一个包含所有key的list
  • D.values() #返回一个包含所有值的list
  • D.items() #返回一个以(key:value)为成员的list
  • D.get(k[, x]) For example D.get(‘key’,'None’)
    #取D[k]的值,如果没有分键k,则返回x。如果k没有,x也没有提供则返回None。注意即使k不存在,D也没有改变,并不会把k:x加到D中。
  • D.setdefault(k[,x])
    #与get()一样,会返回D[k]。但如果k没有,k:x这个成员会被添加到D中。返回x
  • D.clear() #清除D中的内容
  • D.copy() #返回一个新的dictionary,它是D的拷贝
  • D.pop(k[,x]) #与setdefault()类似。在返回D[k]的同时,会把k:value这个成员删除,D会改变。如果没有提供x,而且k又不存在,会出现一个KeyError
  • D.popitem() #在D返回一个key:value对,然后在D中删除它
  • D.update([b]) #应用b的值,来更新D。b可以是其他的mapping类型,也可以是遍历时每次取出的是一个只有两个成员的tuple的类型,比如:[(1,'one'), (2:'two')],这个list在遍历时,取出的值是(1,’one’)和(2, ‘two’)。还可以用”key=value,…”这样的参数。有一个zip()内置函数在这里特别有用,zip(seq1,seq2…)返回一个以tuple为成员的list,第一个tuple包含一个seq1的第一个值,seq2的第一个值…。
  • D.fromkeys(seq[,value]) #以seq为keys,创建一个新dictionary,如果没有提供value,则各key的值为None。注意这里会创建一个新dictionary,而不是改变原来的dictionary,如果要用原来的符号标识新dictionary,应该用D=D.fromkeys(k)的形式。
    在前面说到用for … in …的方式来遍历一个list,其实这种方式也可以用来遍历一个dictionary。dictionary是由key:value组成的,那么:
  • for x in D
  • x每次取的值是什么呢?先来看几个函数:
  • D.iterkeys()
  • D.itervalues()
  • D.iteritems()

这三个函数均返回一个iterator对象,分别是keys\values\items的iterator。可以用在for循环中。比如:

  • for x in D.iterkeys()

上面说到的for x in D实际上就是这种形式的简写,x遍历的是keys。如果要遍历values,也很简单只要把D.iterkeys()改为D.itervalues()就可以了。iteritems()也类似。在iterator对象中有一个next()的方法,可以像for一样,一次一次的调用next()方法,可以遍历iterator中的数据。

转载的哦!!

深入python

Filed under: python — admin @ 4:50 下午

深入#

让我们暂时将 第一份 Python 程序 抛在脑后,来聊一聊数据类型。在 Python 中, 每个值都有一种数据类型,但您并不需要声明变量的数据类型。那该方式是如何运作的呢?Python 根据每个变量的初始赋值情况分析其类型,并在内部对其进行跟踪。

Python 有多种内置数据类型。以下是比较重要的一些:

  1. Booleans[布尔型] 或为 True[真] 或为 False[假]
  2. Numbers[数值型] 可以是 Integers[整数](12)、Floats[浮点数](1.11.2)、Fractions[分数](1/22/3);甚至是 Complex Number[复数]
  3. Strings[字符串型] 是 Unicode 字符序列,例如: 一份 HTML 文档。
  4. Bytes[字节]Byte Arrays[字节数组]例如: 一份 JPEG 图像文件。
  5. Lists[列表] 是值的有序序列。
  6. Tuples[元组] 是有序而不可变的值序列。
  7. Sets[集合] 是装满无序值的包裹。
  8. Dictionaries[字典] 是键值对的无序包裹。

当然,还有更多的类型。在 Python 中一切均为对象,因此存在像 module[模块]function[函数]class[类]method[方法]file[文件] 甚至 compiled code[已编译代码] 这样的类型。您已经见过这样一些例子:模块的 name函数的 docstrings 等等。将学到的包括 《类 迭代器》 中的 Classes[类],以及 《文件》 中的 Files[文件]。

Strings[字符串]和 Bytes[字节串]比较重要,也相对复杂,足以开辟独立章节予以讲述。让我们先看看其它类型。

布尔类型#

在布尔类型上下文中,您几乎可以使用任何表达式。

布尔类型或为真或为假。Python 有两个被巧妙地命名为 TrueFalse 的常量,可用于对布尔类型的直接赋值。表达式也可以计算为布尔类型的值。在某些地方(如 if 语句),Python 所预期的就是一个可计算出布尔类型值的表达式。这些地方称为 布尔类型上下文环境。事实上,可在布尔类型上下文环境中使用任何表达式,而 Python 将试图判断其真值。在布尔类型上下文环境中,不同的数据类型对于何值为真、何值为假有着不同的规则。(看过本章稍后的实例后,这一点将更好理解。)

例如,看看 humansize.py 中的这个片段:

if size < 0: 
    raise ValueError('number must be non-negative')

size 是整数, 0 是整数,而 < 是数字运算符。size < 0 表达式的结果始终是布尔值。可在 Python 交互式 shell 中自行测试下结果:

>>> size = 1
>>> size < 0
False
>>> size = 0
>>> size < 0
False
>>> size = -1
>>> size < 0
True

由于 Python 2 的一些遗留问题,布尔值可以当做数值对待。True1False 为 0 。

>>> True + True
2
>>> True - False
1
>>> True * False
0
>>> True / False
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ZeroDivisionError: int division or modulo by zero

喔,喔,喔!别那么干。忘掉我刚才说的。

数值类型#

数值类型是可畏的。有太多类型可选了。Python 同时支持 Integer[整型]Floating Point[浮点型] 数值。无任何类型声明可用于区分;Python 通过是否有 小数 点来分辨它们。

跳过该代码清单


>>> type(1) <class 'int'> >>> isinstance(1, int) True >>> 1 + 1 2 >>> 1 + 1.0 2.0 >>> type(2.0) <class 'float'>
可以使用 type() 函数来检测任何值或变量的类型。正如所料,1int 类型。
同样,还可使用 isinstance() 函数判断某个值或变量是否为给定某个类型。
将一个 int 与一个 int 相加将得到一个 int
将一个 int 与一个 float 相加将得到一个 float 。Python 把 int 强制转换为 float 以进行加法运算;然后返回一个 float 类型的结果。

将整数强制转换为浮点数及反向转换#

正如刚才所看到的,一些运算符(如:加法)会根据需把整数强制转换为浮点数。也可自行对其进行强制转换。

跳过该代码清单



通过调用float() 函数,可以显示地将 int 强制转换为 float
毫不出奇,也可以通过调用 int()float 强制转换为 int
int() 将进行取整,而不是四舍五入。
对于负数,int() 函数朝着 0 的方法进行取整。它是个真正的取整(截断)函数,而不是 floor[地板]函数。
浮点数精确到小数点后 15 位。
整数可以任意大。

☞Python 2 对于int[整型]long[长整型] 采用不同的数据类型。int 数据类型受到 sys.maxint 的限制,因平台该限制也会有所不同,但通常是 232-1 。Python 3 只有一种整数类型,其行为方式很有点像 Python 2 的旧 long[长整数] 类型。参阅 PEP 237 了解更多细节。

常见数值运算#

对数值可进行各种类型的运算。

跳过该代码清单



/ 运算符执行浮点除法。即便分子和分母都是 int,它也返回一个 float 浮点数。
// 运算符执行古怪的整数除法。如果结果为正数,可将其视为朝向小数位取整(不是四舍五入),但是要小心这一点。
当整数除以负数, // 运算符将结果朝着最近的整数“向上”四舍五入。从数学角度来说,由于 −6−5 要小,它是“向下”四舍五入,如果期望将结果取整为 −5,它将会误导你。
// 运算符并非总是返回整数结果。如果分子或者分母是 float,它仍将朝着最近的整数进行四舍五入,但实际返回的值将会是 float 类型。
** 运算符的意思是“计算幂”,112 结果为 121
% 运算符给出了进行整除之后的余数。11 除以 2 结果为 5 以及余数 1,因此此处的结果为 1

☞在 Python 2 中,运算符 / 通常表示整数除法,但是可以通过在代码中加入特殊指令,使其看起来像浮点除法。在 Python 3 中,/ 运算符总是表示浮点除法。参阅 PEP 238 了解更多细节。

分数#

Python 并不仅仅局限于整数和浮点数类型。它可以完成你在高中阶段学过、但几乎已经全部忘光的所有古怪数学运算。

跳过该代码清单


>>> import fractions >>> x = fractions.Fraction(1, 3) >>> x Fraction(1, 3) >>> x * 2 Fraction(2, 3) >>> fractions.Fraction(6, 4) Fraction(3, 2) >>> fractions.Fraction(0, 0) Traceback (most recent call last): File "<stdin>", line 1, in <module> File "fractions.py", line 96, in __new__ raise ZeroDivisionError('Fraction(%s, 0)' % numerator) ZeroDivisionError: Fraction(0, 0)
为启用 fractions 模块,必先引入 fractions 模块。
为定义一个分数,创建一个 Fraction 对象并传入分子和分母。
可对分数进行所有的常规数学计算。运算返回一个新的 Fraction 对象。2 * (1/3) = (2/3)
Fraction 对象将会自动进行约分。(6/4) = (3/2)
在杜绝创建以零为分母的分数方面,Python 有着良好的敏感性。

三角函数#

还可在 Python 中进行基本的三角函数运算。

跳过该代码清单


>>> import math >>> math.pi 3.1415926535897931 >>> math.sin(math.pi / 2) 1.0 >>> math.tan(math.pi / 4) 0.99999999999999989
math 模块中有一个代表 π 的常量,表示圆的周长与直径之比率(圆周率)。
math 模块包括了所有的基本三角函数,包括:sin()cos()tan() 及像 asin() 这样的变体函数。
然而要注意的是 Python 并不支持无限精度。tan(π / 4) 将返回 1.0,而不是 0.99999999999999989

布尔上下文环境中的数值#

零值是 false[假],非零值是 true[真]。

可以在 if 这样的 布尔类型上下文环境中 使用数值。零值是 false[假],非零值是 true[真]。

跳过该代码清单


>>> def is_it_true(anything): ...   if anything: ...     print("yes, it's true") ...   else: ...     print("no, it's false") ... >>> is_it_true(1) yes, it's true >>> is_it_true(-1) yes, it's true >>> is_it_true(0) no, it's false >>> is_it_true(0.1) yes, it's true >>> is_it_true(0.0) no, it's false >>> import fractions >>> is_it_true(fractions.Fraction(1, 2)) yes, it's true >>> is_it_true(fractions.Fraction(0, 1)) no, it's false
您知道可以在 Python 交互式 Shell 中定义自己的函数吗?只需在每行的结尾按 回车键 ,然后在某一空行按 回车键 结束。
在布尔类型上下文环境中,非零整数为真;零为假。
非零浮点数为真; 0.0 为假。请千万小心这一点!如果有轻微的四舍五入偏差(正如在前面小节中看到的那样,这并非不可能的事情),那么 Python 将测试 0.0000000000001 而不是 0 ,并将返回一个 True 值。
分数也可在布尔类型上下文环境中使用。无论 n 为何值,Fraction(0, n) 为假。所有其它分数为真。

列表#

列表是 Python 的主力数据类型。当提到 “列表 ”时,您脑海中可能会闪现“必须进一步声明大小的数组,只能包含同一类对象“ 等想法。千万别这么想。列表比那要酷得多。

☞ Python 中的列表类似 Perl 5 中的数组。在 Perl 5 中,存储数组的变量总是以字符 @ 开头;在 Python 中,变量可随意命名,Python 仅在内部对数据类型进行跟踪。

☞ Python 中的列表更像 Java 中的数组(尽管可以把列表当做生命中所需要的一切来使用)。一个更好的比喻可能是 ArrayList 类,该类可以容纳任何对象,并可在添加新元素时进行动态拓展。

创建列表#

列表创建非常轻松:使用中括号包裹一系列以逗号分割的值即可。

跳过该代码清单


>>> a_list = ['a', 'b', 'mpilgrim', 'z', 'example'] >>> a_list ['a', 'b', 'mpilgrim', 'z', 'example'] >>> a_list[0] 'a' >>> a_list[4] 'example' >>> a_list[-1] 'example' >>> a_list[-3] 'mpilgrim'
首先,创建一个包含 5 个元素的列表。要注意的是它们保持了最初的顺序。这并不是偶然的。列表是元素的有序集合。
列表可当做以零为基点的数组使用。非空列表的首个元素始终是 a_list[0]
该 5 元素列表的最后一个元素是 a_list[4],因为列表(索引)总是以零为基点的。
使用负索引值可从列表的尾部向前计数访问元素。任何非空列表的最后一个元素总是 a_list[-1]
如果负数令你混淆,可将其视为如下方式: a_list[-n] == a_list[len(a_list) - n] 。因此在此列表中, a_list[-3] == a_list[5 - 3] == a_list[2]

列表切片#

a_list[0] 是列表的第一个元素。

定义列表后,可从其中获取任何部分作为新列表。该技术称为对列表进行 切片

跳过该代码清单


>>> a_list ['a', 'b', 'mpilgrim', 'z', 'example'] >>> a_list[1:3] ['b', 'mpilgrim'] >>> a_list[1:-1] ['b', 'mpilgrim', 'z'] >>> a_list[0:3] ['a', 'b', 'mpilgrim'] >>> a_list[:3] ['a', 'b', 'mpilgrim'] >>> a_list[3:] ['z', 'example'] >>> a_list[:] ['a', 'b', 'mpilgrim', 'z', 'example']
通过指定两个索引值,可以从列表中获取称作“切片”的某个部分。返回值是一个新列表,它包含列表(??切片)中所有元素,按顺序从第一个切片索引开始(本例中为 a_list[1]),截止但不包含第二个切片索引(本例中的 a_list[3])。
如果切片索引之一或两者均为负数,切片操作仍可进行。如果有帮助的话,您可以这么思考:自左向右读取列表,第一个切片索引指明了想要的第一个元素,第二个切片索引指明了第一个不想要的元素。返回值是两者之间的任何值。 between.
列表是以零为起点的,因此 a_list[0:3] 返回列表的头三个元素,从 a_list[0] 开始,截止到但不包括 a_list[3]
如果左切片索引为零,可以将其留空而将零隐去。因此 a_list[:3]a_list[0:3] 是完全相同的,因为起点 0 被隐去了。
同样,如果右切片索引为列表的长度,也可以将其留空。因此 a_list[3:]a_list[3:5] 是完全相同的,因为该列表有五个元素。此处有个好玩的对称现象。在这个五元素列表中, a_list[:3] 返回头三个元素,而 a_list[3:] 返回最后两个元素。事实上,无论列表的长度是多少, a_list[:n] 将返回头 n 个元素,而 a_list[n:] 返回其余部分。
如果两个切片索引都留空,那么将包括列表所有的元素。但该返回值与最初的 a_list 变量并不一样。它是一个新列表,只不过恰好拥有完全相同的元素而已。a_list[:] 是对列表进行复制的一条捷径。

向列表中新增项#

有四种方法可用于向列表中增加元素。

跳过该代码清单


>>> a_list = ['a'] >>> a_list = a_list + [2.0, 3] >>> a_list ['a', 2.0, 3] >>> a_list.append(True) >>> a_list ['a', 2.0, 3, True] >>> a_list.extend(['four', 'Ω']) >>> a_list ['a', 2.0, 3, True, 'four', 'Ω'] >>> a_list.insert(0, 'Ω') >>> a_list ['Ω', 'a', 2.0, 3, True, 'four', 'Ω']
+ 运算符连接列表以创建一个新列表。列表可包含任何数量的元素;没有大小限制(除了可用内存的限制)。然而,如果内存是个问题,那就必须知道在进行连接操作时,将在内存中创建第二个列表。在该情况下,新列表将会立即被赋值给已有变量 a_list 。因此,实际上该行代码包含两个步骤 — 连接然后赋值 — 当处理大型列表时,该操作可能(暂时)消耗大量内存。
列表可包含任何数据类型的元素,单个列表中的元素无须全为同一类型。下面的列表中包含一个字符串、一个浮点数和一个整数。
append() 方法向列表的尾部添加一个新的元素。(现在列表中有 四种 不同数据类型!)
列表是以类的形式实现的。“创建”列表实际上是将一个类实例化。因此,列表有多种方法可以操作。extend() 方法只接受一个列表作为参数,并将该参数的每个元素都添加到原有的列表中。
insert() 方法将单个元素插入到列表中。第一个参数是列表中将被顶离原位的第一个元素的位置索引。列表中的元素并不一定要是唯一的;比如说:现有两个各自独立的元素,其值均为 'Ω':,第一个元素 a_list[0] 以及最后一个元素 a_list[6]

a_list.insert(0, value) 就像是 Perl 中的 unshift() 函数。它将一个元素添加到列表的头部,所有其它的元素都被顶理原先的位置以腾出空间。

让我们进一步看看 append()extend() 的区别。

跳过该代码清单


>>> a_list = ['a', 'b', 'c'] >>> a_list.extend(['d', 'e', 'f']) >>> a_list ['a', 'b', 'c', 'd', 'e', 'f'] >>> len(a_list) 6 >>> a_list[-1] 'f' >>> a_list.append(['g', 'h', 'i']) >>> a_list ['a', 'b', 'c', 'd', 'e', 'f', ['g', 'h', 'i']] >>> len(a_list) 7 >>> a_list[-1] ['g', 'h', 'i']
extend() 方法只接受一个参数,而该参数总是一个列表,并将列表 a_list 中所有的元素都添加到该列表中。
如果开始有个 3 元素列表,然后将它与另一个 3 元素列表进行 extend 操作,结果是将获得一个 6 元素列表。
另一方面, append() 方法只接受一个参数,但可以是任何数据类型。在此,对一个 3 元素列表调用 append() 方法。
如果开始的时候有个 6 元素列表,然后将一个列表 append[添加]上去,结果就会……得到一个 7 元素列表。为什么是 7 个?因为最后一个元素(刚刚 append[添加] 的元素) 本身是个列表 。列表可包含任何类型的数据,包括其它列表。这可能是你所需要的结果,也许不是。但如果这就是你想要的,那这就是你所得到的。

在列表中检索值#

跳过该代码清单


>>> a_list = ['a', 'b', 'new', 'mpilgrim', 'new'] >>> a_list.count('new') 2 >>> 'new' in a_list True >>> 'c' in a_list False >>> a_list.index('mpilgrim') 3 >>> a_list.index('new') 2 >>> a_list.index('c') Traceback (innermost last): File "<interactive input>", line 1, in ?ValueError: list.index(x): x not in list
如你所期望, count() 方法返回了列表中某个特定值出现的次数。
如果你想知道的是某个值是否出现在列表中, in 运算符将会比使用 count() 方法要略快一些。in 运算符总是返回 TrueFalse;它不会告诉你该值出现在什么位置。
如果想知道某个值在列表中的精确位置,可调用 index() 方法。尽管可以通过第二个参数(以 0 为基点的)索引值来指定起点,通过第三个参数(以 0 基点的)索引来指定搜索终点,但缺省情况下它将搜索整个列表,
index() 方法将查找某值在列表中的第一次出现。在该情况下,'new' 在列表中出现了两次,分别为 a_list[2]a_list[4],但 index() 方法将只返回第一次出现的位置索引值。
可能 出乎 您的预期,如果在列表中没有找到该值,index() 方法将会引发一个例外。

等等,什么?是这样的:如果没有在列表中找到该值, index() 方法将会引发一个例外。这是 Python 语言最显著不同之处,其它多数语言将会返回一些无效的索引值(像是 -1)。当然,一开始这一点看起来比较讨厌,但我想您会逐渐欣赏它。这意味着您的程序将会在问题的源头处崩溃,而不是之后奇怪地、默默地崩溃。请记住, -1 是合法的列表索引值。如果 index() 方法返回 -1,可能会导致调整过程变得不那么有趣!

从列表中删除元素#

列表永远不会有缝隙。

列表可以自动拓展或者收缩。您已经看到了拓展部分。也有几种方法可从列表中删除元素。

跳过该代码清单


>>> a_list = ['a', 'b', 'new', 'mpilgrim', 'new'] >>> a_list[1] 'b' >>> del a_list[1] >>> a_list ['a', 'new', 'mpilgrim', 'new'] >>> a_list[1] 'new'
可使用 del 语句从列表中删除某个特定元素。
删除索引 1 之后再访问索引 1不会 导致错误。被删除元素之后的所有元素将移动它们的位置以“填补”被删除元素所产生的“缝隙”。

不知道位置索引?这不成问题,您可以通过值而不是索引删除元素。

跳过该代码清单


>>> a_list.remove('new') >>> a_list ['a', 'mpilgrim', 'new'] >>> a_list.remove('new') >>> a_list ['a', 'mpilgrim'] >>> a_list.remove('new') Traceback (most recent call last): File "<stdin>", line 1, in <module> ValueError: list.remove(x): x not in list
还可以通过 remove() 方法从列表中删除某个元素。remove() 方法接受一个 value 参数,并删除列表中该值的第一次出现。同样,被删除元素之后的所有元素将会将索引位置下移,以“填补缝隙”。列表永远不会有“缝隙”。
您可以尽情地调用 remove() 方法,但如果试图删除列表中不存在的元素,它将引发一个例外。

Removing Items From A List: Bonus Round#

另一有趣的列表方法是 pop()pop() 方法是从列表删除元素的另一方法,但有点变化。

跳过该代码清单


>>> a_list = ['a', 'b', 'new', 'mpilgrim'] >>> a_list.pop() 'mpilgrim' >>> a_list ['a', 'b', 'new'] >>> a_list.pop(1) 'b' >>> a_list ['a', 'new'] >>> a_list.pop() 'new' >>> a_list.pop() 'a' >>> a_list.pop() Traceback (most recent call last): File "<stdin>", line 1, in <module> IndexError: pop from empty list
如果不带参数调用, pop() 列表方法将删除列表中最后的元素,并返回所删除的值
可以从列表中 pop[弹出]任何元素。只需传给 pop() 方法一个位置索引值。它将删除该元素,将其后所有元素移位以“填补缝隙”,然后返回它删除的值。
对空列表调用 pop() 将会引发一个例外。

☞不带参数调用的 pop() 列表方法就像 Perl 中的 pop() 函数。它从列表中删除最后一个元素并返回所删除元素的值。Perl 还有另一个函数 shift(),可用于删除第一个元素并返回其值;在 Python 中,该函数相当于 a_list.pop(0)

布尔上下文环境中的列表#

空列表为假;其它所有列表为真。

可以在 if 这样的 布尔类型上下文环境中 使用列表。

跳过该代码清单


>>> def is_it_true(anything): ...   if anything: ...     print("yes, it's true") ...   else: ...     print("no, it's false") ... >>> is_it_true([]) no, it's false >>> is_it_true(['a']) yes, it's true >>> is_it_true([False]) yes, it's true
在布尔类型上下文环境中,空列表为假值。
任何至少包含一个上元素的列表为真值。
任何至少包含一个上元素的列表为真值。元素的值无关紧要。

元组#

元素 是不可变的列表。一旦创建之后,用任何方法都不可以修改元素。

跳过该代码清单


>>> a_tuple = ("a", "b", "mpilgrim", "z", "example") >>> a_tuple ('a', 'b', 'mpilgrim', 'z', 'example') >>> a_tuple[0] 'a' >>> a_tuple[-1] 'example' >>> a_tuple[1:3] ('b', 'mpilgrim')
元组的定义方式和列表相同,除了整个元素的集合都用圆括号,而不是方括号闭合。
和列表一样,元组的元素都有确定的顺序。元组的索引也是以零为基点的,和列表一样,因此非空元组的第一个元素总是 a_tuple[0]
负的索引从元组的尾部开始计数,这和列表也是一样的。
和列表一样,元组也可以进行切片操作。对列表切片可以得到新的列表;对元组切片可以得到新的元组。

元组和列表的主要区别是元组不能进行修改。用技术术语来说,元组是 不可变更 的。从实践的角度来说,没有可用于修改元组的方法。列表有像 append()extend()insert()remove()pop() 这样的方法。这些方法,元组都没有。可以对元组进行切片操作(因为该方法创建一个新的元组),可以检查元组是否包含了特定的值(因为该操作不修改元组),还可以……就那么多了。

跳过该代码清单


# continued from the previous example >>> a_tuple ('a', 'b', 'mpilgrim', 'z', 'example') >>> a_tuple.append("new") Traceback (innermost last): File "<interactive input>", line 1, in ?AttributeError: 'tuple' object has no attribute 'append' >>> a_tuple.remove("z") Traceback (innermost last): File "<interactive input>", line 1, in ?AttributeError: 'tuple' object has no attribute 'remove' >>> a_tuple.index("example") 4 >>> "z" in a_tuple True
无法向元组添加元素。元组没有 append()extend() 方法。
不能从元组中删除元素。元组没有 remove()pop() 方法。
可以 在元组中查找元素,由于该操作不改变元组。
还可以使用 in 运算符检查某元素是否存在于元组中。

那么元组有什么好处呢?

  • 元组的速度比列表更快。如果定义了一系列常量值,而所需做的仅是对它进行遍历,那么请使用元组替代列表。
  • 对不需要改变的数据进行“写保护”将使得代码更加安全。使用元组替代列表就像是有一条隐含的 assert 语句显示该数据是常量,特别的想法(及特别的功能)必须重写。(??)
  • 一些元组可用作字典键(特别是包含字符串、数值和其它元组这样的不可变数据的元组)。列表永远不能当做字典键使用,因为列表不是不可变的。

☞元组可转换成列表,反之亦然。内建的 tuple() 函数接受一个列表参数,并返回一个包含同样元素的元组,而 list() 函数接受一个元组参数并返回一个列表。从效果上看, tuple() 冻结列表,而 list() 融化元组。

布尔上下文环境中的元组#

可以在 if 这样的 布尔类型上下文环境中 使用元组。

跳过该代码清单


>>> def is_it_true(anything):
...   if anything:
...     print("yes, it's true")
...   else:
...     print("no, it's false")
...
>>> is_it_true(())
no, it's false
>>> is_it_true(('a', 'b'))
yes, it's true
>>> is_it_true((False,))
yes, it's true
>>> type((False))

十一月 29, 2010

python 异常捕获与处理

Filed under: python — admin @ 2:20 下午

python异常except语句用法与引发异常

except: #捕获所有异常

except: <异常名>: #捕获指定异常

except:<异常名1,异常名2):捕获异常1或者异常2

except:<异常名>,<数据>:捕获指定异常及其附加的数据

except:<异常名1,异常名2>:<数据>:捕获异常名1或者异常名2,及附加的数据库

常用异常名:

异常名    描述
AttributeError 调用不存在的方法引发的异常
EOFError     遇到文件末尾引发的异常
ImportError 导入模块出错引发的异常
IndexError     列表越界引发的异常
IOError     I/O操作引发的异常,如打开文件出错等
KeyError   使用字典中不存在的关键字引发的异常
NameError 使用不存在的变量名引发的异常
TabError 语句块缩进不正确引发的异常
ValueError 搜索列表中不存在的值引发的异常
ZeroDivisionError   除数为零引发的异常

使用raise 引发异常几种方式:

raise 异常名
raise 异常名,附加数据
raise 类名

assert 简化了raise语句:
需要注意的是,assert语句一般用于开发时对程序条件的验证,只有当内置_debug_为True时,assert语句才有效。当Python脚本以-O选项编译成为字节码文件时,assert 语句将被移除。
但与raise语句不同的是,assert语句是在条件测试为假时,才引发异常。assert语言的一般形式如下:

assert <条件测试>,<异常附加数据> #其中异常附加数据是可选的

顺便加点python切片的

option=sys.argv[1][2:]

意思是切第2个参数的 第3个字符开始到结束

转载著名(LINUXQQ)

十一月 28, 2010

python sys.exit() 错误

Filed under: python — admin @ 7:56 下午

 windows 下运行

import sys

sys.exit()

提示 Traceback (most recent call last):
  File “C:/Python31/try”, line 7, in <module>
    sys.exit()
SystemExit

解释原因:sys.exit()是退出python解释器回到上级shell,IDLE最高级别就是就是python解释器,没法退。。

转载注明(LINUXQQ)

python 3.x open

Filed under: python — admin @ 7:02 下午

1.open
使用open打开文件后一定要记得调用文件对象的close()方法。比如可以用try/finally语句来确保最后能关闭文件。
file_object = open(‘thefile.txt’)
try:
 all_the_text = file_object.read( )
finally:
 file_object.close( )
注:不能把open语句放在try块里,因为当打开文件出现异常时,文件对象file_object无法执行close()方法。
2.读文件
读文本文件
input = open(‘data’, ‘r’)
#第二个参数默认为r
input = open(‘data’)
读二进制文件
input = open(‘data’, ‘rb’)

读取所有内容
file_object = open(‘thefile.txt’)
try:
 all_the_text = file_object.read( )
finally:
 file_object.close( )

读固定字节
file_object = open(‘abinfile’, ‘rb’)
try:
 while True:
 chunk = file_object.read(100)
 if not chunk:
 break
 do_something_with(chunk)
finally:
 file_object.close( )

读每行
list_of_all_the_lines = file_object.readlines( )
如果文件是文本文件,还可以直接遍历文件对象获取每行:
for line in file_object:
 process line

3.写文件
写文本文件
output = open(‘data’, ‘w’)

写二进制文件
output = open(‘data’, ‘wb’)

追加写文件
output = open(‘data’, ‘w+’)

写数据
file_object = open(‘thefile.txt’, ‘w’)
file_object.write(all_the_text)
file_object.close( )

写入多行
file_object.writelines(list_of_text_strings)
注意,调用writelines写入多行在性能上会比使用write一次性写入要高。

以下是个例子

#!/usr/bin/python
import pickle as p
shoplistfile=’shoplist.data’
shoplist=['apple','mango','carrot']
f=open(shoplistfile,’wb’)
p.dump(shoplist,f)
f.close()
del shoplist
f=open(shoplistfile,’rb’)
storedlist=p.load(f)
print (storedlist)

python进行文件读写的函数是open或file

file_handler = open(filename,,mode)

Table mode

模式 描述
r 以读方式打开文件,可读取文件信息。
w 以写方式打开文件,可向文件写入信息。如文件存在,则清空该文件,再写入新内容
a 以追加模式打开文件(即一打开文件,文件指针自动移到文件末尾),如果文件不存在则创建
r+ 以读写方式打开文件,可对文件进行读和写操作。
w+ 消除文件内容,然后以读写方式打开文件。
a+ 以读写方式打开文件,并把文件指针移到文件尾。
b 以二进制模式打开文件,而不是以文本模式。该模式只对Windows或Dos有效,类Unix的文件是用二进制模式进行操作的。

 

Table 文件对象方法

方法 描述
f.close() 关闭文件,记住用open()打开文件后一定要记得关闭它,否则会占用系统的可打开文件句柄数。
f.fileno() 获得文件描述符,是一个数字
f.flush() 刷新输出缓存
f.isatty() 如果文件是一个交互终端,则返回True,否则返回False。
f.read([count]) 读出文件,如果有count,则读出count个字节。
f.readline() 读出一行信息。
f.readlines() 读出所有行,也就是读出整个文件的信息。
f.seek(offset[,where]) 把文件指针移动到相对于where的offset位置。where为0表示文件开始处,这是默认值 ;1表示当前位置;2表示文件结尾。
f.tell() 获得文件指针位置。
f.truncate([size]) 截取文件,使文件的大小为size。
f.write(string) 把string字符串写入文件。
f.writelines(list) 把list中的字符串一行一行地写入文件,是连续写入文件,没有换行。

 

例子如下:

读文件

Python代码

  • read = open(result)   
  •        line=read.readline()   
  •        while line:   
  •              print line   
  •              line=read.readline()#如果没有这行会造成死循环   
  •        read.close  
  •  read = open(result)
            line=read.readline()
            while line:
                  print line
                  line=read.readline()#如果没有这行会造成死循环
            read.close

     写文件

    Python代码

  • read = file(result,’a+’)   
  •         read.write(“\r\n”)   
  •         read.write(“thank you”)   
  •         read.close  
  • read = file(result,'a+')
            read.write("\r\n")
            read.write("thank you")
            read.close

     其它

    Python代码

  • #-*- encoding:UTF-8 -*-   
  • filehandler = open(‘c:\\111.txt’,'r’)    #以读方式打开文件,rb为二进制方式(如图片或可执行文件等)   
  •   
  • print ’read() function:’              #读取整个文件   
  • print filehandler.read()   
  •   
  • print ’readline() function:’          #返回文件头,读取一行   
  • filehandler.seek(0)   
  • print filehandler.readline()   
  •   
  • print ’readlines() function:’         #返回文件头,返回所有行的列表   
  • filehandler.seek(0)   
  • print filehandler.readlines()   
  •   
  • print ’list all lines’                #返回文件头,显示所有行   
  • filehandler.seek(0)   
  • textlist = filehandler.readlines()   
  • for line in textlist:   
  •     print line,   
  • print    
  • print  
  •   
  • print ’seek(15) function’               #移位到第15个字符,从16个字符开始显示余下内容   
  • filehandler.seek(15)   
  • print ’tell() function’  
  • print filehandler.tell()              #显示当前位置   
  • print filehandler.read()   
  •   
  • filehandler.close()                   #关闭文件句柄  
  • linux 平台推送数据

    Filed under: linux — admin @ 5:56 下午

    一、 前言 
    作为一种优秀的编程语言,Java在许多方面具有突出的优越性。其中,RMI技术充分展现了Java卓越的分布式计算能力,而JNI技术则体现了Java结合异种编程语言的强大能力。人们常说,RMI是“从Java到Java”,这种说法忽视了这样一个事实:Java可利用JNI技术很容易地与原有系统连接。JNI+RMI的技术解决方案极大地延伸了Java的分布式功能。 
    本文的写作是基于这样一种实际需要:在实际运行环境当中,我们需要将一台Linux网络工作站产生的信息实时动态的显示在远程监控者的机器上,以便他及时对该Linux工作站上发生的情况进行处理。比如, Linux工作站上运行着网络入侵检测系统,检测到的入侵信息必须实时地提供给远程监控者,以便及时作出响应;再比如, Linux工作站上运行着网络管理系统,产生的有关网络流量和网络性能的数据也必须及时提供给网络管理人员。 
    而Linux平台下的软件,大多数是用C语言编写的,这是一笔难以舍弃的财富。而且C语言与底层系统的紧密结合以及C的运行速度,是Java所不具备。这就为JNI+RMI技术提供了广阔的舞台。 

    二、 JNI技术 
    Java以其跨平台的特性得到广泛应用,其代码可以一次编译多处执行。但正是这种特性 给它带来了一定的局限性,一些与平台相关的功能就不能很好地支持。幸运的是Java提供了JNI技术——完备的C语言接口,让我们可以利用C语言的强大功能来弥补Java的不足。很容易发现JNI在Java和本地应用程序之间起着胶水的作用。图1将描述JNI是如何将应用程序的C语言部分和Java部分连接在一起的。图1来源于Sun公司的Java指南。 

    三、 RMI技术 
    1、 运行原理 
    RMI 应用程序通常包括两个独立的程序:服务器程序和客户机程序。典型的服务器应用程序将创建多个远程对象,使这些远程对象能够被引用,然后等待客户机调用那些远程对象上的方法。而典型的客户机程序则从服务器中得到一个或多个远程对象的引用,然后调用远程对象的方法。RMI 为服务器和客户机进行通讯和信息传递提供了一种机制。这样的应用程序有时被称为分布式对象应用程序。分布式对象应用程序需要:(1)定位远程对象。它既可用 RMI 的简单命名工具 rmiregistry 来注册它的远程对象,也可将远程对象引用作为常规操作的一部分来进行传递和返回。(2)与远程对象通讯。远程对象间通讯的细节由 RMI 处理,对于程序员来说,远程通讯看起来就象标准的 Java 方法调用。(3)给作为参数或返回值传递的对象加载类字节码。因为 RMI 允许调用程序将纯 Java 对象传给远程对象,所以 RMI 将提供必要的机制,既可以加载对象的代码又可以传输对象的数据。服务器调用注册服务程序以使名字与远程对象相关联。客户机在服务器注册服务程序中用远程对象的名字查找该远程对象,然后调用它的方法。RMI 能用 Java系统支持的任何 URL 协议(例如 HTTP、FTP、file 等)加载类字节码。 
    下图描绘了一个RMI分布式应用程序 ,它通过registry得到一个远程对象的引用。服务器调用registry将远程对象连接(或者绑定)到一个名字上。客户端在服务器的 registry上根据那个名字查找远程对象,并且调用名字上的一个方法。图2同时显示出每当需要时,RMI系统使用一个Web服务器来装载类字节码,从服务器到客户端并且从顾客到服务器。图2来源于Sun公司的Java指南。 

    2、 双向RMI技术 
    前面讲到通常情况下在RMI应用程序中,是服务器程序提供远程方法给客户机程序调用。但是某种情况下,RMI应用程序同时也需要客户机程序提供远程方法给服务器程序调用。也就是说,某种情况下,RMI应用程序的两个部分同时具有服务器和客户机的功能。 
    比如,你的远程客户希望可以通过浏览器实时查看Linux平台下程序运行的产生的信息。那么从技术上说:远程客户机器上运行的Applet程序是RMI服务器程序,而Linux平台下程序是RMI客户机程序。Linux平台下程序通过RMI调用Applet程序的相关方法,将信息实时推送到远程客户机器。这是一个非常典型的RMI应用。 
    但是这里出现了一个问题:远程客户机器的IP地址没有办法确定,远程客户应该可以从任何连接到Internet的机器上访问到这些信息。如果不知道IP地址,Linux平台下程序不可能通过URL访问远程Applet程序中的RMI方法。 
    因此这里必须使用双向RMI技术。首先由远程Applet程序通过URL调用Linux平台下程序的RMI方法,建立起RMI连接。然后,再由Linux平台下程序调用远程Applet程序中RMI来推送信息。 

    四、 程序实例 
    关于Linux平台下C程序的输出,可以是网络入侵检测系统,网络管理系统,或者其他系统。这里为了简化程序,用一个简单的C程序代替。该程序将你在Linux平台下输入的字符串,回显到远端客户浏览器上。 
    1、 编写Java文件CreatMessage.java 
    里面包含一些native的函数,这些函数就是将在C中要实现的。另外程序将声明一个调用RMI方法的Java私有方法,该方法将在C程序中被调用。源程序如下: 
    class CreatMessage{ 
    MessageServerImpl ms; 
    //声明一个本地方法接口函数 
    public native void creatmsa(); 
    //声明一个Java方法,该方法将在C程序中被调用 
    private void pushMessage(String message){ 
    //新建一个RMI远程对象,并对其赋值 
    Message msa = new Message(); 
    msa.MessageString = message; 
    // notifyEvent方法将调用RMI方法notifiedEvent(Message msa) 
    try{ 
    ms.notifyEvent(msa); 
    } catch(Exception e){ 
    System.out.println(“notifyEvent Exception:”+e.getMessage()); 
    }//catch end 

    //构造函数负责传递MessageServerImpl对象的实例 
    public CreatMessage(MessageServerImpl msserver){ 
    ms = msserver; 

    2、 编译CreatMessage.java文件,生成C语言头文件CreatMessage.h 
    用Javac CreatMessage.java命令编译Java源文件,生成CreatMessage.class,再用Javah CreatMessage命令生成C语言头文件CreatMessage.h 
    /* DO NOT EDIT THIS FILE – it is machine generated */ 
    #include <jni.h> 
    /* Header for class CreatMessage */ 
    #ifndef _Included_CreatMessage 
    #define _Included_CreatMessage 
    #ifdef __cplusplus 
    extern “C” { 
    #endif 
    /* 
    * Class: CreatMessage 
    * Method: creatmsa 
    * Signature: ()V 
    */ 
    JNIEXPORT void JNICALL Java_CreatMessage_creatmsa 
    (JNIEnv *, jobject); 
    #ifdef __cplusplus 

    #endif 
    #endif 
    这是由javah命令生成的文件,不需要也不允许进行任何修改。我们注意到这里有一段程序 “JNIEXPORT void JNICALL Java_CreatMessage_creatmsa (JNIEnv *, jobject);”。Java_CreatMessage_creatmsa 提供了CreatMessage.class中本地方法的具体实现,当你编写本地方法的实现程序时,你将使用相同的方法签名。如果CreatMessage.class含有其他的本地方法,这些方法的签名同样会在头文件中出现。 

    3、 编写creatmsa.c,实现本地方法 
    首先我们将如何得到Java方法的签名呢?有两种方法,一种是依据生成规则手工推算,另外Java 类文件反汇编程序工具javap ,可以帮助你消除手工推算方法签名时发生的错误。你能使用javap工具为指定的类打印出成员变量和方法签名:javap -s -p CreatMessage。 
    要在C程序中调用Java方法,需要完成下面三个步骤: 
    (1) 在C程序中调用JNI方法GetObjectClass,它将返回该Java对象的Java类对象。 
    (2) 接着调用JNI方法GetMethodID,它将在一个给定的类文件中查找Java方法。该查找是基于方法名字以及方法签名。如果该方法不存在,GetMethodID将返回0。程序将立即返回,并抛出NoSuchMethodError。 
    (3) 将调用JNI方法CallVoidMethod。该方法将激活一个返回值为void的实例方法。你必须将object, method ID以及该方法的参数传递给CallVoidMethod。 

    creatmsa.c源程序如下: 
    #include <stdio.h> 
    #include <jni.h> 
    #include “CreatMessage.h” 
    static jclass cls ; 
    static jmethodID mid ; 
    JNIEXPORT void JNICALL Java_CreatMessage_creatmsa(JNIEnv *env, jobject obj) 

    char buff[128]; 
    jstring message; 
    //将用户输入字符串,赋值给buff 
    scanf(“%s”, buff); 
    //将buff的值转换成UTF格式,并赋给message 
    message = (*env)->NewStringUTF(env,buff); 
    cls = (*env)->GetObjectClass(env, obj); 
    mid = (*env)->GetMethodID(env, cls, “pushMessage”, “(Ljava/lang/String;)V”); 
    if (mid == 0){ 
    printf(“GetMethodID error”); 
    return; 

    (*env)->CallVoidMethod(env, obj, mid, message); 

    4、 编译creatmsa.c,生成libcreatmsa.so 
    在Linux平台下编译creatmsa.c,要格外注意路径问题。最经常出现的错误就是因为路径设置不对,而引起的无法找到编译所需要的文件。本文中使用jdk1.3.1的目录为/url/local/j2sdk1.3.1,所有例子程序都存放在/rmitest目录下。因此本文路径设置为: 
    classpath = /rmitest: 
    /url/local/j2sdk1.3.1/include: 
    /url/local/j2sdk1.3.1/jre/lib/i386 
    export classpath 
    LD_LIBRARY_PATH = /rmitest: 
    /url/local/j2sdk1.3.1/jre/lib/i386: 
    /url/local/j2sdk1.3.1/jre/lib/i386/native_threads: 
    /url/local/j2sdk1.3.1/jre/lib/i386/classic: 
    $LD_LIBRARY_PATH 
    export LD_LIBRARY_PATH 
    设置完路径以后,就可以开始编译程序了,使用命令: 
    gcc -I//url/local/j2sdk1.3.1/include 
    -I//url/local/j2sdk1.3.1/include/linux 
    -shared 
    creatmsa.c -o libcreatmsa.so 

    5、 Message.java 
    在RMI分布式应用系统中,服务器与客户机之间传递的Java对象必须是可序列化的对象。不可序列化的对象不能在对象流中进行传递。因此,我们必须生成一个Java类以传递参数。这个类定义的很简单,在实际运用中,可以根据需要增加内容。 
    import java.io.Serializable; 
    import java.io.*; 
    public class Message implements Serializable 

    String MessageString; 

    6、 MessageServer.java 
    定义两个RMI接口。它们将在MessageServerImpl.java程序中实现。 
    import java.rmi.Remote; 
    import java.rmi.RemoteException; 
    public interface MessageServer extends Remote { 
    void newClient(MessageClient mc) throws RemoteException; 
    void removeClient(MessageClient mc) throws RemoteException; 

    7、 MessageServerImpl.java 
    实现在MessageServer.java程序中定义的RMI接口。 
    import java.rmi.*; 
    import java.rmi.server.*; 
    import java.util.Vector; 
    public class MessageServerImpl extends UnicastRemoteObject implements MessageServer 

    Vector clients=new Vector(); 
    public MessageServerImpl() throws RemoteException { 
    super(); 

    public void newClient(MessageClient mc) throws RemoteException { 
    clients.addElement(mc); 

    public void removeClient(MessageClient mc) throws RemoteException { 
    clients.removeElement(mc); 

    public void notifyEvent(Message msa) throws RemoteException { 
    Vector tc=(Vector)clients.clone(); 
    for (int i=0;i<tc.size();i++){ 
    try { 
    ((MessageClient)(tc.elementAt(i))).notifiedEvent(msa); 
    } catch(Exception e){ 
    removeClient((MessageClient)(tc.elementAt(i))); 



    8、 MessageClient.java 
    定义两个RMI接口。它们将在MessageClientImpl.java程序中实现。 
    import java.rmi.Remote; 
    import java.rmi.RemoteException; 
    public interface MessageClient extends Remote { 
    void notifiedEvent(Message msa) throws RemoteException; 

    9、 MessageClientImpl.java 
    实现在MessageClient.java程序中定义的RMI接口。 
    import java.rmi.*; 
    import java.rmi.server.*; 
    import javax.swing.*; 
    import java.awt.*; 
    public class MessageClientImpl extends UnicastRemoteObject implements MessageClient 

    JTextArea jt; 
    static String ipAddr=”255.255.255.255″; 
    public void notifiedEvent(Message msa) throws RemoteException { 
    jt.insert(msa.MessageString+”\n”,0); 

    public MessageClientImpl(JTextArea jtext) throws RemoteException { 
    super();//调用其父类的构造函数UnicastRemoteObject 
    jt=jtext; 

    public void init() throws RemoteException{ 
    try { 
    String name = “//”+ipAddr+”:1099/MessageServer”; 
    MessageServer fs = (MessageServer)Naming.lookup(name); 
    fs.newClient(this); 
    } catch(Exception e){ 
    System.err.println(“MessageClient exception: ” + e.getMessage()); 


    public void setIPaddr(String str) 

    ipAddr = str; 

    10、 编译生成Stub文件 
    利用命令rmic -v1.2 MessageClientImpl和命令rmic -v1.2 MessageServerImpl 
    分别生成MessageClientImpl_Stub.class文件和MessageServerImpl_Stub.class文件 

    11、 StartServer.java 
    编写StartServer.java文件,初始化RMI运行环境如启动rmigegistry,设置RMISecurityManager,绑定RMI对象等等。并加栽C程序生成的动态连接库文件libcreatmsa.so。 
    import java.rmi.*; 
    import java.rmi.RemoteException; 
    import java.rmi.RMISecurityManager; 
    import java.rmi.registry.LocateRegistry; 
    public class StartServer{ 
    static { 
    System.loadLibrary(“creatmsa”);/*actual name is “libcreatmsa.so”*/ 

    public static void main(String args[]) 

    if(System.getSecurityManager() == null) 
    System.setSecurityManager(new RMISecurityManager()); 
    try{ 
    LocateRegistry.createRegistry(1099); 
    //注册IDS处理服务器 
    MessageServerImpl msObj = new MessageServerImpl(); 
    Naming.rebind(“//127.0.0.1:1099/MessageServer”,msObj); 
    //启动c程序 
    CreatMessage cm = new CreatMessage(msObj); 
    cm.creatmsa(); 
    } catch (Exception e){ 
    System.out.println(“registe error: ” + e.getMessage()); 


    12、 MessageEcho.java 
    编写远程客户端的Applet程序,调用RMI方法,与服务器建立连接。并一个Panel上显示Linux平台下程序产生的数据。 
    import java.awt.*; 
    import java.applet.Applet; 
    import javax.swing.*; 
    import java.rmi.RMISecurityManager; 
    public class MessageEcho extends JApplet{ 
    Container contentPane = getContentPane(); 
    JPanel panel = new JPanel(new BorderLayout()); 
    JPanel alarmPanel;//显示Linux平台下程序产生的数据的模板 
    //显示Linux平台下程序产生的数据的区域 
    final JTextArea alarmList=new JTextArea(8,40); 
    //运行Linux平台下程序的机器的IP地址 
    String ipServer; 
    public void init() { 
    ipServer = getParameter(“AppServer”); //此项在test.html中赋值 
    alarmPanel=new JPanel(); 
    alarmList.insert(“\nSome message here”+”\n”,0); 
    alarmPanel.setLayout(null); 
    alarmList.setLineWrap(true); 
    alarmList.setWrapStyleWord(true); 
    JScrollPane areaScrollPane = new JScrollPane(alarmList); 
    areaScrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS); 
    areaScrollPane.setPreferredSize(new Dimension(200, 120)); 
    alarmPanel.add(areaScrollPane); 
    areaScrollPane.setBounds(0,40,200,120); 
    panel.add(alarmPanel,BorderLayout.CENTER); 
    contentPane.add(panel); 
    try{ 
    MessageClientImpl mci=new MessageClientImpl(alarmList); 
    mci.setIPaddr(ipServer); 
    mci.init(); 
    } catch (Exception e) { 
    System.err.println(“alarmListener exception: ” + e.getMessage()); 
    e.printStackTrace(); 


    13、 Test.html 
    在HTML文件中调用Applet的类文件。其中AppServer是Linux工作站的IP地址。 
    <HTML> 
    <BODY> 
    <COMMENT> 
    <EMBED width=”750″ height=”400″ 
    align=”baseline” code=”MessageEcho.class” codebase=”.” 
    AppServer=”202.114.33.87″ ><!–应用服务器地址,即Linux工作站的IP地址–> 
    </EMBED> 
    </BODY> 
    </HTML> 

    14、 修改java.policy文件 
    为了允许客户程序同RMI注册程序和服务器对象连接,你需要提供一个策略文件(policy file)。策略文件是非常复杂的问题。这里只提供一个修改的样本,它赋予程序绝大多数的操作权限。这样使你调试类似程序时候非常方便,但是也请注意这种做法给你的计算机带来的潜在危险。希望进一步了解安全策略文件的读者可以看看参考文献8。 
    java.policy文件内容如下: 
    grant { 
    permission java.security.AllPermission; 
    }; 
    因为本文中使用的是双向RMI,所以你必须同时修改两台机器的策略文件。在RedHat7.1中需要将java.policy文件拷贝到/url/local/j2sdk1.3.1/jre/lib/security目录,在Windows2000中是c:\j2sdk1.3.1\jre\lib\security目录。当然你需要根据你机器上的java目录做相应调整。 

    五、 实现环境以及运行步骤 
    一台机器操作系统为RedHat7.1,文件有:MessageServer.class,MessageServerImpl.class,MessageServerImpl_Stub.class,Message.class,MessageClient.class,MessageClientImpl_Stub.class,libcreatmsa.so,所有文件均在同一目录下面。 
    一台机器操作系统为Windows2000,文件有:MessageClient.class,MessageClientImpl.class,MessageClientImpl_Stub.class,Message.class,MessageServer.class,MessageServerImpl_Stub.class,MessageEcho.class,test.html,所有文件均在同一目录下面。 
    1、 首先修改两台机器上的java.policy文件; 
    2、 然后在RedHat7.1的机器上设置路径,即运行上文提到的相应命令; 
    3、 然后在RedHat7.1的机器上运行命令:java StartServer; 
    4、 然后在Windows2000的机器上运行命令:appletviewer test.html; 
    5、 接着在RedHat7.1的机器上随意输入一字符传后敲回车键,该字符串将回显在Windows2000机器的Appletviewer窗口中

    转载(http://www.blogjava.net/codefans/articles/18436.html)

    十一月 27, 2010

    linux ext3 ext4区别

    Filed under: linux — admin @ 12:08 下午

    Linux kernel 自 2.6.28 开始正式支持新的文件系统 Ext4。 Ext4 是 Ext3 的改进版,修改了 Ext3 中部分重要的数据结构,而不仅仅像 Ext3 对 Ext2 那样,只是增加了一个日志功能而已。Ext4 可以提供更佳的性能和可靠性,还有更为丰富的功能:

    1. 与 Ext3 兼容。执行若干条命令,就能从 Ext3 在线迁移到 Ext4,而无须重新格式化磁盘或重新安装系统。原有 Ext3 数据结构照样保留,Ext4 作用于新数据,当然,整个文件系统因此也就获得了 Ext4 所支持的更大容量。

    2. 更大的文件系统和更大的文件。较之 Ext3 目前所支持的最大 16TB 文件系统和最大 2TB 文件,Ext4 分别支持 1EB(1,048,576TB, 1EB=1024PB, 1PB=1024TB)的文件系统,以及 16TB 的文件。

    3. 无限数量的子目录。Ext3 目前只支持 32,000 个子目录,而 Ext4 支持无限数量的子目录。

    4. Extents。Ext3 采用间接块映射,当操作大文件时,效率极其低下。比如一个 100MB 大小的文件,在 Ext3 中要建立 25,600 个数据块(每个数据块大小为 4KB)的映射表。而 Ext4 引入了现代文件系统中流行的 extents 概念,每个 extent 为一组连续的数据块,上述文件则表示为“该文件数据保存在接下来的 25,600 个数据块中”,提高了不少效率。

    5. 多块分配。当写入数据到 Ext3 文件系统中时,Ext3 的数据块分配器每次只能分配一个 4KB 的块,写一个 100MB 文件就要调用 25,600 次数据块分配器,而 Ext4 的多块分配器“multiblock allocator”(mballoc) 支持一次调用分配多个数据块。

    6. 延迟分配。Ext3 的数据块分配策略是尽快分配,而 Ext4 和其它现代文件操作系统的策略是尽可能地延迟分配,直到文件在 cache 中写完才开始分配数据块并写入磁盘,这样就能优化整个文件的数据块分配,与前两种特性搭配起来可以显著提升性能。

    7. 快速 fsck。以前执行 fsck 第一步就会很慢,因为它要检查所有的 inode,现在 Ext4 给每个组的 inode 表中都添加了一份未使用 inode 的列表,今后 fsck Ext4 文件系统就可以跳过它们而只去检查那些在用的 inode 了。

    8. 日志校验。日志是最常用的部分,也极易导致磁盘硬件故障,而从损坏的日志中恢复数据会导致更多的数据损坏。Ext4 的日志校验功能可以很方便地判断日志数据是否损坏,而且它将 Ext3 的两阶段日志机制合并成一个阶段,在增加安全性的同时提高了性能。

    9. “无日志”(No Journaling)模式。日志总归有一些开销,Ext4 允许关闭日志,以便某些有特殊需求的用户可以借此提升性能。

    10. 在线碎片整理。尽管延迟分配、多块分配和 extents 能有效减少文件系统碎片,但碎片还是不可避免会产生。Ext4 支持在线碎片整理,并将提供 e4defrag 工具进行个别文件或整个文件系统的碎片整理。

    11. inode 相关特性。Ext4 支持更大的 inode,较之 Ext3 默认的 inode 大小 128 字节,Ext4 为了在 inode 中容纳更多的扩展属性(如纳秒时间戳或 inode 版本),默认 inode 大小为 256 字节。Ext4 还支持快速扩展属性(fast extended attributes)和 inode 保留(inodes reservation)。

    12. 持久预分配(Persistent preallocation)。P2P 软件为了保证下载文件有足够的空间存放,常常会预先创建一个与所下载文件大小相同的空文件,以免未来的数小时或数天之内磁盘空间不足导致下载失败。 Ext4 在文件系统层面实现了持久预分配并提供相应的 API(libc 中的 posix_fallocate()),比应用软件自己实现更有效率。

    13. 默认启用 barrier。磁盘上配有内部缓存,以便重新调整批量数据的写操作顺序,优化写入性能,因此文件系统必须在日志数据写入磁盘之后才能写 commit 记录,若 commit 记录写入在先,而日志有可能损坏,那么就会影响数据完整性。Ext4 默认启用 barrier,只有当 barrier 之前的数据全部写入磁盘,才能写 barrier 之后的数据。(可通过 “mount -o barrier=0″ 命令禁用该特性。)
    Ext4 随 Linux kernel 2.6.28 正式发布已有数周,一直苦于找不到测试用的磁盘,正巧年前 Intel 送来几块 SSD 测试样品,这两天就顺带把 SSD 也测了。测试所使用的 Linux 内核版本为 2.6.28.2,测试工具为 IOzone 3.318。

    IOzone 测试命令为:

    time /opt/iozone/bin/iozone -a -s 4G -q 256 -y 4 >|/root/ext4-iozone-stdout.txt
    上述命令的说明如下:

        Auto Mode
        File size set to 4194304 KB
        Using Maximum Record Size 256 KB
        Using Minimum Record Size 4 KB
        Command line used: /opt/iozone/bin/iozone -a -s 4G -q 256 -y 4
        Output is in Kbytes/sec
        Time Resolution = 0.000001 seconds.
        Processor cache size set to 1024 Kbytes.
        Processor cache line size set to 32 bytes.
        File stride size set to 17 * record size.
    测试结果除了表明 Intel SSD 的读写速度快得令人咋舌之外,还可以说明 Ext4 的各方面性能都超过了上一代 Ext3,甚至在大多数情况下,比没有日志功能的 Ext2 还要快出不少:

      reclen write rewrite read reread random read random write
    Ext2 4 218,680 216,596 630,248 245,802 88,700 138,065
      8 215,308 218,690 556,064 246,260 154,680 150,052
    real 28m12.718s 16 216,457 216,843 575,046 245,701 258,660 158,750
    user 0m10.725s 32 217,925 214,289 537,976 243,081 394,013 167,002
    sys 5m8.265s 64 215,460 219,256 527,919 244,362 503,227 162,917
      128 219,081 216,173 540,831 242,526 609,750 161,442
      256 216,091 217,631 565,111 245,157 654,274 173,955
    Ext3 4 218,242 213,039 482,132 243,986 88,007 156,926
      8 218,390 217,915 544,892 244,979 152,424 190,454
    real 27m42.449s 16 218,083 217,683 561,038 244,506 255,244 200,032
    user 0m11.529s 32 216,258 217,013 569,246 243,811 389,745 198,275
    sys 7m17.049s 64 218,850 217,711 577,529 243,725 497,689 201,693
      128 220,234 215,687 530,519 241,615 608,244 199,619
      256 216,011 220,188 592,578 242,548 642,341 199,408
    Ext4 4 221,823 216,992 532,488 273,668 85,210 183,195
      8 226,028 218,580 561,960 272,036 154,972 216,505
    real 27m3.485s 16 222,241 217,746 547,548 270,895 260,899 223,895
    user 0m10.847s 32 220,121 213,025 240,426 247,628 345,210 175,977
    sys 6m9.578s 64 223,983 214,437 308,696 551,577 754,941 225,897
      128 222,576 217,816 624,636 271,293 644,500 224,997
      256 221,202 222,238 541,685 270,898 671,748 228,085
                   
                   
      bkwd read record rewrite stride read fwrite frewrite fread freread
    Ext2 106,112 1,882,623 73,538 214,175 218,364 566,570 247,381
      188,397 2,462,367 130,896 217,157 216,647 583,808 248,397
    real 28m12.718s 306,842 2,654,320 220,939 216,061 218,140 598,174 246,581
    user 0m10.725s 464,240 2,397,831 340,775 217,434 219,353 583,463 246,341
    sys 5m8.265s 609,546 2,546,079 456,243 216,875 217,692 571,707 244,264
      721,701 2,656,729 551,122 217,780 217,427 579,271 242,291
      870,547 2,574,261 634,835 216,638 219,693 563,735 247,101
    Ext3 105,557 1,540,739 75,010 216,028 216,432 522,704 243,385
      181,486 1,945,603 130,737 218,364 216,431 530,853 243,222
    real 27m42.449s 300,212 2,096,495 221,329 216,930 216,661 514,177 244,069
    user 0m11.529s 446,462 1,934,853 338,785 216,809 219,296 530,634 243,446
    sys 7m17.049s 589,535 2,036,412 450,449 219,387 214,900 514,353 244,809
      714,295 1,992,168 553,022 217,828 218,454 513,596 241,510
      834,240 2,092,959 624,043 217,682 218,165 529,358 242,878
    Ext4 103,036 1,862,817 74,781 225,841 220,620 523,799 272,848
      178,482 2,135,372 132,506 227,423 215,766 641,021 271,328
    real 27m3.485s 295,288 2,095,966 223,135 226,055 216,210 621,287 273,475
    user 0m10.847s 451,631 2,145,351 342,236 225,796 213,427 598,331 269,759
    sys 6m9.578s 523,130 2,218,016 448,086 227,030 214,706 582,795 272,323
      720,468 2,308,315 582,943 225,971 217,373 552,335 274,237
      845,494 2,215,381 643,715 225,411 219,166 580,066 273,342

    注:
    1. 关于 IOzone 测试方法,参考 Ben Martin 的文章:IOzone for filesystem performance benchmarking
    2. 关于 Ext4 的相关内容,参考 Kernel Newbies 专页: http://kernelnewbies.org/Ext4

    十一月 26, 2010

    数据时时同步

    Filed under: 乱7八糟 — admin @ 8:42 下午

    本项目利用inotify与rsync对服务器进行实时同步,其中inotify用于监控文件系统事件,rsync是目前广泛使用的同步算法,其优点是只对文件不同的部分进行操作,所以其优势大大超过使用挂接文件系统的方式进行镜像同步。
    目前使用的比较多的同步程序版本是inotify-tools,另外一个是google开源项目Openduckbill(依赖于inotify-tools),这两个都是基于脚本语言编写的,其设计思路同样是采用inotify与rsync命令。 相比较上面两个项目,本项目优点是:
    1.sersync是使用c++编写,而且对linux系统文件系统产生的临时文件和重复的文件操作进行过滤(我稍后会提到),所以在结合rsync同步的时候,节省了运行时耗和网络资源。因此更快。
    2.相比较上面两个项目,sersync配置起来很简单:在http://code.google.com/p/sersync/downloads/list 处下载源码(分为32版本,与64位版本),其中bin目录下已经有我编译好的2进制文件,配合bin目录下的xml文件直接使用即可。
    3.另外本项目相比较其他脚本开源项目,使用多线程进行同步,尤其在同步较大文件时,能够保证多个服务器实时保持同步状态。
    4.本项目自带出错处理机制,通过失败队列对出错的文件重新出错,如果仍旧失败,则每10个小时对同步失败的文件重新同步。
    5.本项目自带crontab功能,只需在xml配置文件中开启,即可按您的要求,隔一段时间整体同步一次。
    6.本项目自带socket与http协议扩展,满足您二次开发的需要。
    sersync下载地址:在http://code.google.com/p/sersync/downloads/list

    源服务器OS:Centos 5.5 64位系统

    目标服务器:Freebsd 7.2 Centos 5.5

    规模:10台

    需求:从源服务器实时推送数据到目标服务器

    源服务器布署:

    下载64位Sersync二进安装包:

    #wget http://sersync.googlecode.com/files/sersync2.5_64bit_binary_stable_final.tar.gz

    #tar -xzvf sersync2.5_64bit_binary_stable_final.tar.gz

    # cd GNU-Linux-x86/

    [root@localhost GNU-Linux-x86]# ll
    total 1588
    -rwxr-xr-x 1 root root    2214 Jun 29 07:19 confxml.xml
    -rwxr-xr-x 1 root root 1617440 Jun 29 07:12 sersync2

     编辑confxml.xml文件:

    <?xml version=”1.0″ encoding=”ISO-8859-1″?>
    <head version=”2.5″>
        <host hostip=”localhost” port=”8008″></host> #本地主机配置
        <debug start=”false”/>
        <fileSystem xfs=”false”/>
        <filter start=”false”>
            <exclude expression=”(.*)\.svn”></exclude>
            <exclude expression=”(.*)\.gz”></exclude>
            <exclude expression=”^info/*”></exclude>
            <exclude expression=”^static/*”></exclude>
        </filter>
        <inotify>
            <delete start=”true”/>
            <createFolder start=”true”/>
            <createFile start=”false”/>
            <closeWrite start=”true”/>
            <moveFrom start=”true”/>
            <moveTo start=”true”/>
            <attrib start=”false”/>
            <modify start=”false”/>
        </inotify>

        <sersync>

        <localpath watch=”/usr/local/www/apache22/data/mj/Data”>#watch填写需同步的源服务器本地路径
          <remote ip=”192.168.8.39″/>#remote填写同步的远程目标主机IP与模块名称

          <remote ip=”192.168.8.40″/>    
         </localpath>
            <rsync>
                <commonParams params=”-artuz”/>
                <auth start=”false” users=”root” passwordfile=”/etc/rsync.pas”/>
                <userDefinedPort start=”false” port=”874″/>
                <timeout start=”false” time=”100″/>
                <ssh start=”false”/>
            </rsync>
            <failLog path=”/tmp/rsync_fail_log.sh” timeToExecute=”60″/>
            <crontab start=”false” schedule=”600″>#start标签设置为true,即设定多长时间对监控项目彻底同步一次
                <crontabfilter start=”false”>#plugin标签是在同步过程中使用插件
                    <exclude expression=”*.php”></exclude>
                    <exclude expression=”info/*”></exclude>
                </crontabfilter>
            </crontab>
            <plugin start=”false”/>
        </sersync>

        <plugin>
            <param prefix=”/bin/sh” suffix=”" ignoreError=”true”/> 
            <filter start=”false”>
                <include expression=”(.*)\.php”/>
                <include expression=”(.*)\.sh”/>
            </filter>
        </plugin>

        <plugin>#socket插件标签
            <localpath watch=”/opt/tongbu”>
                <deshost ip=”192.168.138.20″ port=”8009″/>
            </localpath>
        </plugin>
        <plugin>#CDN插件标签
            <localpath watch=”/data0/htdocs/cms.xoyo.com/site/”>
                <cdninfo domainname=”ccms.chinacache.com” port=”80″ username=”xxxx” passwd=”xxxx”/>
                <sendurl base=”http://pic.xoyo.com/cms”/>
                <regexurl regex=”false” match=”cms.xoyo.com/site([/a-zA-Z0-9]*).xoyo.com/images”/>
            </localpath>
        </plugin>
    </head>

    保存并退出

    运行Sersync与Sersync启动参数
    ./sersync -r

    如果需要将sersync运行前,已经存在的所有文件或目录全部同步到远程,要以-r参数运行sersync,将本地与远程整体同步一次。
    如果设置了过滤器,即在xml文件中,filter为true,则暂时不能使用-r参数进行整体同步。-r参数将会无效

    3.查看启动参数帮助

    ./sersync –help


    4.指定配置文件
    ./sersync -o XXXX.xml

    对于sersync使用可执行文件目录下的默认配置文件confxml.xml,如果需要使用另一个配置文件,可以使用-o参数指定其它配置文件。

    5.指定默认的线程池的线程总数
    ./sersync -n num
    例如 ./sersync -n 5 则指定线程总数为5,如果不指定,默认启动线程池数量是10,如果cpu使用过高,可以通过这个参数调低,如果机器配置较高,可以用-n跳高线程总数。

    6.不进行同步,只运行插件
    ./sersync -m pluginName

           例如./sersync -m command,则在监控到文件事件后,不对远程目标服务器进行同步,而是直接运行command插件。

    7.多个参数可以配合使用
    ./sersync -n 8 -o abc.xml -r -d

    表示,设置线程池工作线程为8个,指定abc.xml作为配置文件,在实时监控前作一次整体同步,以守护进程方式在后台运行。

    8.通常情况下,对本地到远程整体同步一遍后,在后台运行实时同步。
    ./sersync -r -d

    9。查看sersync服务是否成功启动!
    ps -aux|grep sersync
    root     13383  0.0  0.0  61204   752 pts/2    S+   19:41   0:00 grep sersync
    root     27853  0.0  0.0 210912   900 ?        Ssl  Oct28   0:00 ./sersync2 -d -r

    目标服务器布署:

    1)基于centos目标服务器布署rsync:

    1、查看是否装了rsync包:
    [root@mj 水瓶]# rpm -q rsync
    rsync-2.6.8-3.1

    如果没有安装就用rpm 或yum装上。

     # yum –y install rsync

    2、新建配置文件/etc/rsyncd.conf,然后编辑/etc/rsyncd.conf,添加一下内容到文件里:

    uid = root
    gid = root
    use chroot = no
    max connections = 30
    syslog facility = local5
    pid file = /var/run/rsyncd.pid
    #lock file = /var/run/rsync.lock
    log file = /var/log/rsyncd.log
    list = false
    ignore errors
    hosts allow = 10.30.71.11  #填写源服务器的IP

    hosts deny = 0.0.0.0/0

    [mj]
                  path = /usr/local/www/apache22/data/mj/Data
                  comment = mjdata
                  read only = false

    保存,并退出!

    3、开启rsync daemon格式
    rsync –daemon 检查rsync是否起来:

    lsof -i :873

    COMMAND PID USER   FD   TYPE DEVICE SIZE NODE NAME
    rsync   2625 root    4u IPv6   5662       TCP *:rsync (LISTEN)
    rsync   2625 root    5u IPv4   5663       TCP *:rsync (LISTEN)

    表示已经起来,返回空,表示没有起来

    确保防火墙能使 tcp的873端口通过

    如果不行请service iptables stop 关闭iptables

    4、把rsync启动加到启动项里
    echo “rsync –daemon ” >>etc/rc.local

    2) 基于Freebsd目标服务器布署rsync:

    1、查看是否装了rsync包:
    99_source# pkg_info|grep rsync

    rsync-3.0.5         A network file distribution/synchronization utility

    如果没有安装就用pkg_add 或portsnap方式装上。

    如:pkg_add -rv rsync

    2、新建配置文件/etc/rsyncd.conf,然后编辑/etc/rsyncd.conf,添加一下内容到文件里:

    uid = www

    gid = www

    use chroot = no

    max connections = 8

    syslog facility = local5

    log file = /var/log/rsyncd.log

    timeout = 600

    hosts allow = 122.173.29.142

    hosts deny = 0.0.0.0/32

    [mj]

          path = /usr/local/www/apache22/data/mj/Data

          comment = mjdata

          read only = false

    保存,并退出!

    3、开启rsync daemon格式
    rsync –daemon –config=/etc/rsyncd.conf

    检查rsync是否起来:

    99_source# ps -aux|grep rsync

    root   69106  0.0  0.0  3128  1380  ??  Is    6:04PM   0:00.00 rsync –config=/etc/rsyncd.conf –daemon

    root   69190  0.0  0.0  1660  1028  p1  D+    6:08PM   0:00.00 grep rsync

    4、把rsync启动加到启动项里
    echo “rsync –daemon –config=/etc/rsyncd.conf” >>/etc/rc.local

    5、目标服务器本地防火墙配置,允许源服务器能上传文件到本地。

    Ipfw add allow tcp from 122.173.29.142to me dst-port 873

    Ipfw add allow tcp from me to 122.173.29.142

    python 类继承

    Filed under: python — admin @ 9:57 上午

    Python 是完全面向对象的:你可以定义自已的类,从自已的或内置的类继承,然后从你定义的类创建实例。

    在 Python 中定义类很简单。就象定义函数,没有单独的接口定义。只要定义类,然后就可以开始编码。Python 类以保留字 class 开始,后面跟着类名。从技术上讲,有这些就够了,因为一个类并非必须从其它类继承。

    例 5.3. 最简单的 Python 类

    class Loaf: 1
        pass    2 3
    1 这个类的名字是 Loaf,它没有从其它类继承。 类名通常是第一个字母大写,如:EachWordLikeThis,但这只是一个习惯,不是一个必要条件。
    2 这个类没有定义任何方法或属性,但是从语法上,需要在定义中有些东西,所以你使用 pass。这是一个 Python 保留字,仅仅表示 “向前走,不要往这看”。它是一条什么都不做的语句,当你删空函数或类时,它是一个很好的占位符。
    3 你可能猜到了,在类中的所有东西都要缩近,就象位于函数、if 语句,for 循环,诸如此类的代码。第一条不缩近的东西不属于这个类。

    注意
    在 Python 中的 pass 语句就象 Java 或 C 中的大括号空集 ({})。

    当然,实际上大多数的类都是从其它的类继承来的,并且它们会定义自已的类方法和属性。但是就象你刚才看到的,除了名字以外,类没有什么必须要具有的。特别是,C++ 程序员可能会感到奇怪,Python 的类没有显示的构造函数和析构函数。Python 类的确存在与构造函数相似的东西: __init__ 方法。

    例 5.4. 定义 FileInfo

    from UserDict import UserDict
    
    class FileInfo(UserDict): 1
    1 在 Python 中,类的基类只是简单地列在类名后面的小括号里。所以 FileInfo 类是从 UserDict 类 (它是从 UserDict 模块导进来的) 继承来的。UserDict 是一个象字典一样工作的类,它允许你完全子类化字典数据类型,同时增加你自已的行为。(也存在相似的类 UserListUserString ,它们允许你子类化列表和字符串。)(译注:在 2.2 之后已经可以从 dict, list 来派生子类了) 在这个类的背后有一些“巫术”,我们将在本章的后面,随着更进一步地研究 UserDict 类,揭开这些秘密。

    注意
    在 Python 中,类的基类只是简单地列在类名后面的小括号里。不象在 Java 中有一个特殊的象 extends 的关键字。

    Python 支持多重继承。在类名后面的小括号中,你可以列出许多你想要的类名,以逗号分隔。

    5.3.1. 初始化并开始类编码

    本例演示了使用 __init__ 方法来进行 FileInfo 类的初始化。

    例 5.5. 初始化 FileInfo Class

    class FileInfo(UserDict):
        "store file metadata"              1
        def __init__(self, filename=None): 2 3 4
    1 类也可以 (并且 应该) 有 doc strings ,就象方法和函数一样。
    2 __init__ 在类的实例创建后被立即调用。它可能会引诱你称之为类的构造函数,但这种说法并不正确。说它引诱,是因为它看上去象(按照习惯, __init__ 是类中第一个定义的方法),行为也象(在一个新创建的类实例中,它是首先被执行的代码),并且叫起来也象(“init”当然意味着构造的本性)。说它不正确,是因为对象在调用 __init__ 时已经被构造出来了,你已经有了一个对类的新实例的有效引用。但 __init__ 是在 Python 中你可以得到的最接近构造函数的东西,并且它也扮演着非常相同的角色。
    3 每个类方法的第一个参数,包括 __init__,都是指向类的当前实例的引用。按照习惯这个参数总是被称为 self。在 __init__ 方法中,self 指向新创建的对象;在其它的类方法中,它指向方法被调用的类实例。尽管当定义方法时你需要明确指定 self,但在调用方法时,你用指定它,Python 会替你自动加上的。
    4 __init__ 方法可以接受任意个数的参数,就象函数一样,参数可以用缺省值定义,可以设置成对于调用者可选。在本例中, filename 有一个缺省值 None,即 Python 的空值。

    注意
    习惯上,任何 Python 类方法的第一个参数(对当前实例的引用)都叫做 self。这个参数扮演着 C++ 或 Java 中的保留字 this 的角色,但 self 在 Python 中并不是一个保留字,它只是一个命名习惯。虽然如此,也请除了 self 之外不要使用其它的名字,这是一个非常坚固的习惯。

    例 5.6. 编写 FileInfo

    class FileInfo(UserDict):
        "store file metadata"
        def __init__(self, filename=None):
            UserDict.__init__(self)        1
            self["name"] = filename        2
                                           3
    1 一些伪面向对象语言,象 Powerbuilder 有一种“扩展”构造函数和其它事件的概念,即父类的方法在子类的方法执行前被自动调用。Python 不是这样,你必须显示地调用在父类中的适合方法。
    2 我告诉过你,这个类象字典一样工作,那么这里就是第一个印象。我们将参数 filename 赋值给对象 name 关键字,作为它的值。
    3 注意 __init__ 方法从不返回一个值。

    5.3.2. 了解何时去使用 self__init__

    当定义你自已的类方法时,你 必须 明确将 self 作为每个方法的第一个参数列出,包括 __init__。当从你的类中调用一个父类的一个方法时,你必须包括 self 参数。但当你从类的外部调用你的类方法时,你不必对 self 参数指定任何值;你完全将其忽略,而 Python 会自动地替你增加实例的引用。我知道刚开始这有些混乱,它并不是自相矛盾的,因为它依靠于一个你还不了解的区别(在绑定与非绑定方法之间),故看上去是矛盾的。

    噢。我知道有很多知识需要吸收,但是你要掌握它。所有的 Python 类以相同的方式工作,所以一旦你学会了一个,就是学会了全部。如果你忘了别的任何事,也要记住这件事,因为我认定它会让你出错:

    注意
    __init__ 方法是可选的,但是一旦你定义了,就必须记得显示调用父类的 __init__ 方法(如果它定义了的话)。这样更是正确的:无论何时子类想扩展父类的行为,后代方法必须在适当的时机,使用适当的参数,显式调用父类方法

    十一月 25, 2010

    linux 内核升级

    Filed under: linux — admin @ 9:13 上午

    网上转载的 具体没有出处!

    Linux kernel 2.4.20升级到Linux kernel 2.6.17

    环境: 主操作系统windows xp  vmware5.5
    虚拟操作系统redhat linux 9  kernel 2.4.20 虚拟硬盘是scsi的

    安装module-init-tools-3.2.tar.gz.
    下载地址:http://www.kernel.org/pub/linux/utils/kernel/module-init-tools/

    # pwd
    /usr/src/
    # tar zxvf module-init-tools-3.2.tar.gz
    # cd module-init-tools-3.2
    # ./configure –prefix=/
    # make moveold
    # make all install
    # ./generate-modprobe.conf  /etc/modprobe.conf

    安装hotplug-ng-002.tar.gz
    如果没有此工具,则USB鼠标即使在启动显示ok 加载上了也不能用
    下载地址:http://www.kernel.org/pub/linux/utils/kernel/hotplug/
    # pwd
    /usr/src/
    # tar zxvf hotplug-ng-002.tar.gz
    # cd hotplug-ng-002
    # make install

    安装linux-2.6.17.tar.bz2
    下载地址:http://www.kernel.org/pub/linux/kernel/v2.6/
    # pwd
    /usr/src/
    # tar xvfj linux-2.6.17.tar.bz2
    # cd linux-2.6.17
    #make menuconfig

    关于”Loadable Module support”选项, 一定要把”Module unloading”和”Automatic kernel module loading”这两个选项编译进内核。
    关于”Block Devices”的配置, 一定要选上对loopback和ramdisk的支持,编译进内核。
    注意,如果你在vmware下重新编译内核,硬盘用的是scsi的,以下选项必选:
    Device Drivers  —>SCSI device support  —><*>   SCSI disk support
    Device Drivers  —>SCSI device support  —>SCSI low-level drivers  —> <*> BusLogic SCSI support
    关于“File system”ext2和ext3文件系统配置为: (全部选择)
    File systems —>
      <*>Second extended fs support
          Ext2 extended attributes
          Ext2 POSIX Access Control Lists
          Ext2 Security Labels
      <*>Ext3 journalling file system support
          <*>Ext3 extended attributes
         <*>Ext3 POSIX Access Control Lists
          <*>Ext3 Security Labels
      <*>JBD (ext3) debugging support

    注意:
       如果你是ext3文件系统,则在定制内核配置文件时把对Ext3、Ext2文件的支持直接编译进内核,否则,等你启用新内核时机器就会当掉,出错信息如下:
          VFS: Cannot open root device “LABEL=/” or 0.0
      Please append a correct “root=” boot option
      kernel panic: VFS: Unable to mount root fs
      把对Ext3、Ext2文件系统的支持直接编译进内核,可解决此问题,还有把对“Module unloading“选项也选上(*),否则的话,你在新内核环境下将无法卸载
    内核模块(rmmod命令不能用)。

    其它选项,我都采用默认的。

    # make dep  (编译2.6内核无需此步骤)
    # make -jn (n代表同时编译的进程,可以加快编译速度,n由你的配置决定。)

    # make bzImage
    # make modules
    # make modules_install  (安装内核模块到/lib/modules/2.x.x下)
    # make install   (完成mkinitrd命令及内核(bzImage)和System.map的拷贝)

    这里如果出现 “NO MODULE BUSLOGIC FOUND”,
    解决方法第1种方法:
    编辑文件 /etc/modules.conf
    将”alias scsi hostadapter BusLogic”这行注释掉,
    即#alias scsi hostadapter BusLogic
    保存 /etc/modules.conf,退出
    第2种方法:
    手动添加启动项
    #depmod -a
    #cp /usr/src/linux/System.map /boot/System.map-2.6.17
    #cp /usr/src/linux/arch/i386/bzImage /boot/vmlinuz-2.6.17

    支持Hotplug
    当然, 首先要在内核配置时配置了HOTPLUG的支持. 然后, 由于/proc/ksyms改名为/proc/kallsyms, 所以必需修改启动脚本/etc/rc.sysinit. 为了兼容原有的linux-2.4.x系统, 可以加上下面几行:

    #
    # —– KERNEL 2.6.x support ——
    # This is for compatibility between kernel-2.4.x and kernel-2.6.x
    #
    UNAME=`uname -r`
    KERNELVER=${UNAME:0:3}
    if [ "$KERNELVER" = "2.6" ]; then
    #
    # This is kernel-2.6.x
    #
    KSYMS=/proc/kallsyms
    else
    #
    # This is kernel-2.4.x
    #
    KSYMS=/proc/ksyms
    fi

    然后, 把rc.sysinit文件中所有出现/proc/ksyms的地方都换成”$KSYMS”变量引用。

    Sysfs问题
    首先, 创建目录/sys:

    # mkdir /sys

    然后, 按照下列步骤修改启动脚本/etc/rc.sysinit文件:

    找到行: mount -f /proc”, 在下面增加:

    if [ "$KERNELVER" = "2.6" ]; then
    mount -f /sys
    fi

    找到行: action $”Mounting proc filesystem: ” mount -n -t proc /proc /proc, 在其下面增加这样一行:

    #
    # Mount /sys for kernel-2.6.x
    #
    if [ "$KERNELVER" = "2.6" ]; then
    action $”Mounting sysfs filesystem: ” mount -n -t sysfs /sys /sys
    fi

    接下来, 在/etc/fstab文件中, 加入这样一行:

    none /sys sysfs defaults 0 0

    最后, 修改/etc/init.d/halt脚本中的halt_get_remaining函数:

    将:
    awk ‘$2 ~ /^\/$|^\/proc|^\/dev/{next}
    改为:
    awk ‘$2 ~ /^\/$|^\/proc|^\/sys|^\/dev/{next}

    支持USB设备

    linux-2.6.x的USB驱动模块的名字已经改变了, 所以由此引起的问题多多……, 对应于USB-2.0的host控制器的内核模块名字仍然是ehci-hcd, 对应USB-1.1的host控制器的内核模块名字已经从usb-ohci改为ochi-hcd, 对应于通用USB host控制器的内核模块名字已经从usb-uhci该为uhci-hcd.

    然而不幸的是, 在安装module-init-tools程序包时生成的/etc/modprobe.conf配置文件却仍然使用usb-ohci这个名字. 例如:

    alias usb-controller usb-ohci
    alias usb-controller1 ehci-hcd

    因此, 要把它改为:

    alias usb-controller ohci-hcd
    alias usb-controller1 ehci-hcd

    如果不做这样的修改, 那么使用USB-1.1 host控制器的机器在启动内核的时候将着不到相应的驱动模块.

    支持USB键盘的模块名字也从keybdev变为usbkbd, 支持USB鼠标的模块名字也从mousedev改为usbmouse. 因此, 我们必需修改启动脚本/etc/rc.sysinit文件. 同时为了兼容原有的2.4.x系统, 我们在脚本的一开始定义两个变量:

    #
    # —– KERNEL 2.6.x support ——
    # This is for compatibility between kernel-2.4.x and kernel-2.6.x
    #
    UNAME=`uname -r`
    KERNELVER=${UNAME:0:3}
    if [ "$KERNELVER" = "2.6" ]; then
    #
    # This is kernel-2.6.x
    #
    KSYMS=/proc/kallsyms
    KEYBDEV_NAME=usbkbd
    MOUSEDEV_NAME=usbmouse
    else
    #
    # This is kernel-2.4.x
    #
    KSYMS=/proc/ksyms
    KEYBDEV_NAME=keybdev
    MOUSEDEV_NAME=mousedev
    fi

    然后, 把/etc/rc.sysinit脚本文件中出现keybdev和mousedev的地方都改为$KEYBDEV_NAME和$MOUSEDEV_NAME. 把脚本文件/etc/rc.sysinit中的needusbstorage部分从:

    needusbstorage=
    if [ $usb = "1" ]; then
    needusbstorage=`LC_ALL=C grep -e “^I.*Cls=08″ /proc/bus/usb/devices 2>/dev/null`
    LC_ALL=C grep ‘hid’ /proc/bus/usb/drivers || action $”Initializing USB HID interface: ” modprobe hid 2> /dev/null

    action $”Initializing USB keyboard: ” modprobe $KEYBDEV_NAME 2> /dev/null
    action $”Initializing USB mouse: ” modprobe $MOUSEDEV_NAME 2> /dev/null
    fi

    改为:

    needusbstorage=
    if [ $usb = "1" ]; then
    if [ "$KERNELVER" = "2.6" ]; then
    needusbstorage=`LC_ALL=C grep -e “^I.*Cls=08″ /sys/bus/usb/devices 2>/dev/null`
    LC_ALL=C grep ‘hid’ /sys/bus/usb/drivers || action $”Initializing USB HID interface: ” modprobe hid 2> /dev/null
    else
    needusbstorage=`LC_ALL=C grep -e “^I.*Cls=08″ /proc/bus/usb/devices 2>/dev/null`
    LC_ALL=C grep ‘hid’ /proc/bus/usb/drivers || action $”Initializing USB HID interface: ” modprobe hid 2> /dev/null
    fi
    action $”Initializing USB keyboard: ” modprobe $KEYBDEV_NAME 2> /dev/null
    action $”Initializing USB mouse: ” modprobe $MOUSEDEV_NAME 2> /dev/null
    fi

    然后重启机器。
    # reboot

    RPM问题
    进入编译好的内核后,与RPM相关的命令有些不能使用,并出现下列错误:
    rpmdb: unable to join the environment
    error: db4 error(11) from dbenv->open: Resource temporarily unavailable
    error: cannot open Packages index using db3 – Resource temporarily unavailable (11)
    error: cannot open Packages database in /var/lib/rpm
    no packages
    解决方法是执行
    #export LD_ASSUME_KERNEL=2.2.25

    回答一:

    没有任何价值的自虐文章。你不知道RH AS4和Fedora Core 5吗?

    回答二:

    呵呵
    我是从不把2.4升级的2,6的 要用2,6还不如下个2.6的源码自己编译的呢 Linux kernel 2.4.20升级到Linux kernel 2.6.17

    环境: 主操作系统windows xp  vmware5.5
    虚拟操作系统redhat linux 9  kernel 2.4.20 虚拟硬盘是scsi的

    安装module-init-tools-3.2.tar.gz.
    下载地址:http://www.kernel.org/pub/linux/utils/kernel/module-init-tools/

    # pwd
    /usr/src/
    # tar zxvf module-init-tools-3.2.tar.gz
    # cd module-init-tools-3.2
    # ./configure –prefix=/
    # make moveold
    # make all install
    # ./generate-modprobe.conf  /etc/modprobe.conf

    安装hotplug-ng-002.tar.gz
    如果没有此工具,则USB鼠标即使在启动显示ok 加载上了也不能用
    下载地址:http://www.kernel.org/pub/linux/utils/kernel/hotplug/
    # pwd
    /usr/src/
    # tar zxvf hotplug-ng-002.tar.gz
    # cd hotplug-ng-002
    # make install

    安装linux-2.6.17.tar.bz2
    下载地址:http://www.kernel.org/pub/linux/kernel/v2.6/
    # pwd
    /usr/src/
    # tar xvfj linux-2.6.17.tar.bz2
    # cd linux-2.6.17
    #make menuconfig

    关于”Loadable Module support”选项, 一定要把”Module unloading”和”Automatic kernel module loading”这两个选项编译进内核。
    关于”Block Devices”的配置, 一定要选上对loopback和ramdisk的支持,编译进内核。
    注意,如果你在vmware下重新编译内核,硬盘用的是scsi的,以下选项必选:
    Device Drivers  —>SCSI device support  —><*>   SCSI disk support
    Device Drivers  —>SCSI device support  —>SCSI low-level drivers  —> <*> BusLogic SCSI support
    关于“File system”ext2和ext3文件系统配置为: (全部选择)
    File systems —>
      <*>Second extended fs support
          Ext2 extended attributes
          Ext2 POSIX Access Control Lists
          Ext2 Security Labels
      <*>Ext3 journalling file system support
          <*>Ext3 extended attributes
         <*>Ext3 POSIX Access Control Lists
          <*>Ext3 Security Labels
      <*>JBD (ext3) debugging support

    注意:
       如果你是ext3文件系统,则在定制内核配置文件时把对Ext3、Ext2文件的支持直接编译进内核,否则,等你启用新内核时机器就会当掉,出错信息如下:
          VFS: Cannot open root device “LABEL=/” or 0.0
      Please append a correct “root=” boot option
      kernel panic: VFS: Unable to mount root fs
      把对Ext3、Ext2文件系统的支持直接编译进内核,可解决此问题,还有把对“Module unloading“选项也选上(*),否则的话,你在新内核环境下将无法卸载
    内核模块(rmmod命令不能用)。

    其它选项,我都采用默认的。

    # make dep  (编译2.6内核无需此步骤)
    # make -jn (n代表同时编译的进程,可以加快编译速度,n由你的配置决定。)

    # make bzImage
    # make modules
    # make modules_install  (安装内核模块到/lib/modules/2.x.x下)
    # make install   (完成mkinitrd命令及内核(bzImage)和System.map的拷贝)

    这里如果出现 “NO MODULE BUSLOGIC FOUND”,
    解决方法第1种方法:
    编辑文件 /etc/modules.conf
    将”alias scsi hostadapter BusLogic”这行注释掉,
    即#alias scsi hostadapter BusLogic
    保存 /etc/modules.conf,退出
    第2种方法:
    手动添加启动项
    #depmod -a
    #cp /usr/src/linux/System.map /boot/System.map-2.6.17
    #cp /usr/src/linux/arch/i386/bzImage /boot/vmlinuz-2.6.17

    支持Hotplug
    当然, 首先要在内核配置时配置了HOTPLUG的支持. 然后, 由于/proc/ksyms改名为/proc/kallsyms, 所以必需修改启动脚本/etc/rc.sysinit. 为了兼容原有的linux-2.4.x系统, 可以加上下面几行:

    #
    # —– KERNEL 2.6.x support ——
    # This is for compatibility between kernel-2.4.x and kernel-2.6.x
    #
    UNAME=`uname -r`
    KERNELVER=${UNAME:0:3}
    if [ "$KERNELVER" = "2.6" ]; then
    #
    # This is kernel-2.6.x
    #
    KSYMS=/proc/kallsyms
    else
    #
    # This is kernel-2.4.x
    #
    KSYMS=/proc/ksyms
    fi

    然后, 把rc.sysinit文件中所有出现/proc/ksyms的地方都换成”$KSYMS”变量引用。

    Sysfs问题
    首先, 创建目录/sys:

    # mkdir /sys

    然后, 按照下列步骤修改启动脚本/etc/rc.sysinit文件:

    找到行: mount -f /proc”, 在下面增加:

    if [ "$KERNELVER" = "2.6" ]; then
    mount -f /sys
    fi

    找到行: action $”Mounting proc filesystem: ” mount -n -t proc /proc /proc, 在其下面增加这样一行:

    #
    # Mount /sys for kernel-2.6.x
    #
    if [ "$KERNELVER" = "2.6" ]; then
    action $”Mounting sysfs filesystem: ” mount -n -t sysfs /sys /sys
    fi

    接下来, 在/etc/fstab文件中, 加入这样一行:

    none /sys sysfs defaults 0 0

    最后, 修改/etc/init.d/halt脚本中的halt_get_remaining函数:

    将:
    awk ‘$2 ~ /^\/$|^\/proc|^\/dev/{next}
    改为:
    awk ‘$2 ~ /^\/$|^\/proc|^\/sys|^\/dev/{next}

    支持USB设备

    linux-2.6.x的USB驱动模块的名字已经改变了, 所以由此引起的问题多多……, 对应于USB-2.0的host控制器的内核模块名字仍然是ehci-hcd, 对应USB-1.1的host控制器的内核模块名字已经从usb-ohci改为ochi-hcd, 对应于通用USB host控制器的内核模块名字已经从usb-uhci该为uhci-hcd.

    然而不幸的是, 在安装module-init-tools程序包时生成的/etc/modprobe.conf配置文件却仍然使用usb-ohci这个名字. 例如:

    alias usb-controller usb-ohci
    alias usb-controller1 ehci-hcd

    因此, 要把它改为:

    alias usb-controller ohci-hcd
    alias usb-controller1 ehci-hcd

    如果不做这样的修改, 那么使用USB-1.1 host控制器的机器在启动内核的时候将着不到相应的驱动模块.

    支持USB键盘的模块名字也从keybdev变为usbkbd, 支持USB鼠标的模块名字也从mousedev改为usbmouse. 因此, 我们必需修改启动脚本/etc/rc.sysinit文件. 同时为了兼容原有的2.4.x系统, 我们在脚本的一开始定义两个变量:

    #
    # —– KERNEL 2.6.x support ——
    # This is for compatibility between kernel-2.4.x and kernel-2.6.x
    #
    UNAME=`uname -r`
    KERNELVER=${UNAME:0:3}
    if [ "$KERNELVER" = "2.6" ]; then
    #
    # This is kernel-2.6.x
    #
    KSYMS=/proc/kallsyms
    KEYBDEV_NAME=usbkbd
    MOUSEDEV_NAME=usbmouse
    else
    #
    # This is kernel-2.4.x
    #
    KSYMS=/proc/ksyms
    KEYBDEV_NAME=keybdev
    MOUSEDEV_NAME=mousedev
    fi

    然后, 把/etc/rc.sysinit脚本文件中出现keybdev和mousedev的地方都改为$KEYBDEV_NAME和$MOUSEDEV_NAME. 把脚本文件/etc/rc.sysinit中的needusbstorage部分从:

    needusbstorage=
    if [ $usb = "1" ]; then
    needusbstorage=`LC_ALL=C grep -e “^I.*Cls=08″ /proc/bus/usb/devices 2>/dev/null`
    LC_ALL=C grep ‘hid’ /proc/bus/usb/drivers || action $”Initializing USB HID interface: ” modprobe hid 2> /dev/null

    action $”Initializing USB keyboard: ” modprobe $KEYBDEV_NAME 2> /dev/null
    action $”Initializing USB mouse: ” modprobe $MOUSEDEV_NAME 2> /dev/null
    fi

    改为:

    needusbstorage=
    if [ $usb = "1" ]; then
    if [ "$KERNELVER" = "2.6" ]; then
    needusbstorage=`LC_ALL=C grep -e “^I.*Cls=08″ /sys/bus/usb/devices 2>/dev/null`
    LC_ALL=C grep ‘hid’ /sys/bus/usb/drivers || action $”Initializing USB HID interface: ” modprobe hid 2> /dev/null
    else
    needusbstorage=`LC_ALL=C grep -e “^I.*Cls=08″ /proc/bus/usb/devices 2>/dev/null`
    LC_ALL=C grep ‘hid’ /proc/bus/usb/drivers || action $”Initializing USB HID interface: ” modprobe hid 2> /dev/null
    fi
    action $”Initializing USB keyboard: ” modprobe $KEYBDEV_NAME 2> /dev/null
    action $”Initializing USB mouse: ” modprobe $MOUSEDEV_NAME 2> /dev/null
    fi

    然后重启机器。
    # reboot

    RPM问题
    进入编译好的内核后,与RPM相关的命令有些不能使用,并出现下列错误:
    rpmdb: unable to join the environment
    error: db4 error(11) from dbenv->open: Resource temporarily unavailable
    error: cannot open Packages index using db3 – Resource temporarily unavailable (11)
    error: cannot open Packages database in /var/lib/rpm
    no packages
    解决方法是执行
    #export LD_ASSUME_KERNEL=2.2.25

    回答一:

    没有任何价值的自虐文章。你不知道RH AS4和Fedora Core 5吗?

    回答二:

    呵呵
    我是从不把2.4升级的2,6的 要用2,6还不如下个2.6的源码自己编译的呢

    Older Posts »

    Powered by LINUXQQ   ICP 10203065