《UNIX/Linux 系统管理技术手册(第四版)》——2.5 Python脚本编程

2.5 Python脚本编程

UNIX/Linux 系统管理技术手册(第四版)
随着项目变得越来越大、越来越复杂,面向对象的设计和实现所带来的好处,也就变得越来越清楚。Perl错过了大概5年时间,没有提供OO特性,虽然它后来又拼命去追赶,但Perl版的面向对象编程仍然显得有点儿牵强。

本节介绍Python 2。Python 3尚在开发之中,可能在本书没过时之前就能发布。但是和Perl 6不一样的是,它看上去更像是一种增量更新。

有着很强OO背景的工程师通常会喜欢Python和Ruby,这两种脚本编程语言都有一种明显的OO特质。目前,Python似乎正处于采纳曲线的下降沿,所以对于系统管理来说,它是一种相当流行的工具。包括OpenSolaris在内的几种操作系统,主要利用了Python的脚本功能。与此相对照,Ruby仍然主要用于Web开发,很少用作一般性的脚本编程。

Guido van Rossum发明了Python。与Perl相比,Python的代码更好写,也更好读。Python提供了一种易于理解的语法,即使没开发过这种代码,也很容易掌握。如果觉得要记住用哪种比较操作符很累人,那么会喜欢上Python整齐划一的方式。Python还提供更多的数据类型,有些系统管理员会发现它们很有用。

如果系统上还没装好Python,可以看看操作系统提供商或者发布方给出的软件包清单。它是一种极其常见的软件包,应该到处都有。如果没找到,可以从python.org下载Python的源代码。这个地方也一个集中位置,可以找到其他人开发的附加模块。

对于Python而言,要想获得比我们在这儿给出的介绍更全面的内容,Mark Pilgrim的Dive Into Python是一个非常好的起步点。从diveintopython.org可以(免费)阅读或者下载这份文档,也可以购买Apress出版的印刷版图书。在2.7节里可以找到完整的参考文献。

2.5.1 Python快速入门
还像往常一样,我们先从一个简单“Hello,world!”脚本开始。果不其然,Python的“Hello, world!”几乎和Perl的一模一样。

#!/usr/bin/python print "Hello,  world!"

要让这个脚本可以运行,只要设置它的可执行位,扩展直接调用python来解释这个脚本:

$ chmod +x  helloworld

$ ./helloworld

Hello, world!

这样的一行程序不能体现出Python对传统的突破,这一突破恶名在外,也就是说,缩行在逻辑上很重要。Python不用花括号、方括号,或者begin和end来界定代码块。处于同一缩进级别的语句自动构成代码块。缩行的风格(空格或者制表符,缩进的深度)则无关紧要。Python的代码分块最好用例子来展示,所以下面就用一条if-then-else语句来说明:

#!/usr/bin/python import sys

a = sys.argv[1]

if a == "1":

print 'a is  one'

print 'This is  still the then clause of  the if statement.'

else:

print 'a is',  a

print 'This is  still the else  clause of  the if statement.'
print 'This is  after the if statement.'

第三行导入sys模块,它包含数组argv。then和else子句都有两行,每一部分都缩进到相同的层次。最后的print语句在if语句之外。和在Perl里的情况一样,Python的print语句也接受任意数量的参数。但和Perl不一样的是,Python自动在每对参数之间都插入一个空格,并提供一个换行符。可以在print行的末尾多加一个逗号,消除这个换行符;参数为空则告诉print不要输出换行符。

在一行末尾的冒号一般是该行引入的一个联系符,它和随后的一个缩进块关联到一起。

$ python blockexample 1

a is  one

This is  still the then clause of  the if statement. This is  after the if statement.

$ python blockexample 2

a is  2

This  is  still the else  clause of  the if statement. This is  after the if statement.

Python的缩行惯例使得代码格式上的灵活度更低了,但它也有优点,即不同的人所编写的代码看上去都一样,而且还意味着不需要搞得代码里到处都有分号,而这些烦人的分号就只为了结束语句。

Python里的注释用一个井号(#)开头,一直持续到行尾,同bash和Perl里的用法一样。

在代码行用反斜线结尾,就可以把长长的代码行分成多行来写。这样做的时候,只有第一行代码的缩进才重要。不过,如果愿意,可以让后续的代码行都缩进。即使没有出现反斜线,但圆括号、方括号或者花括号不配对的代码行仍会自动触发续行,但如果出现这样的情况,可以在代码里包含反斜线,让代码的结构更清晰。

有些剪切和粘贴操作会把制表符(tab)转换为空格,除非知道自己要什么,否则这会让人抓狂。黄金法则是,绝对不要混用制表符和空格;缩进要么用制表符,要么用空格。许多软件采用传统的假设,让制表符应该等于8个空格的距离,对于代码的可读性来说,这确实缩进得太厉害了。大多数Python用户似乎都偏向于采用空格,而且缩进4个字符。

不管决定怎样处理缩行的问题,大多数编辑器都有若干选项,要么只用空白让制表符为非法,要么让空格和制表符显示得不一样,从而帮助用户搞得清楚。在万不得已的情况下,还可以用expand命令把制表符转为空格,或者通过perl -pe命令用一个更容易看到的字符串替换制表符。

2.5.2 对象、字符串、数、列表、字典、元组和文件
Python中所有的数据类型都是对象,比起Perl中的数据类型来说,这一点让它们更强大,也更灵活。

在Python里,列表用方括号而不是圆括号括起来。数组的索引(下标)从0开始,在本章介绍的3种脚本编程语言中,这是为数不多的几种没有变化的概念之一。

Python里新出现了一种叫做“元组(tuple)”的数据类型,它实质上是不能变的列表。元组比数组更快,对于实际上不应该被修改的数据来说,用元组表示更合适。除了用圆括号而不是方括号做定界符之外,元组的语法和列表的一样。因为(thing)看上去是一个简单的代数表达式,因此,对于只包含一个元素的元组,需要用一个额外的逗号来消除它们的含糊意思:(thing, )。

下面是Python中出现的几种基本变量和数据类型:

#!/usr/bin/python name = 'Gwen'

rating = 10

characters = [ 'SpongeBob',  'Patrick', 'Squidward' ]

elements = ( 'lithium', 'carbon', 'boron' )

print "name:\t%s\nrating:\t%d" % (name,  rating)

print "characters:\t%s" % characters print "elements:\t%s" % (elements, )

这个例子产生的输出如下:

$ python objects name: Gwen rating: 10

characters: ['SpongeBob',  'Patrick', 'Squidward']

elements: ('lithium',  'carbon', 'boron')

Python中的变量不会从语法上体现出来,也不会做类型声明,但是它们所指的对象的确有一种支持类型。在大多数情况下,Python不会替用户自动做类型转换,但是单个函数或者操作符可以做转换。例如,不显式地把数值转换为它的字符串表示形式的话,就不能把一个数和一个字符串(用操作符+)连接起来。不过,格式化操作符和语句会强制把所有东西都转为字符串形式。每个对象都有一个字符串表示。

字符串格式化操作符%很像C或者Perl语言里的sprintf函数,但它可以用在字符串出现的任何地方。它是一个双目操作符,左边是字符串,右边是要插入的数值。如果要插入一个以上的数值,那么必须用元组来表示这些值。

Python字典和Perl的哈希一样;也就是说,它是“键/值”对的一个列表。字典常量用花括号括起来,每一对“键/值”都用一个冒号分隔。

#!/usr/bin/python

ordinal = {  1 : 'first', 2 : 'second', 3 : 'third' } print "The  ordinal array contains", ordinal print "The  ordinal of  1 is", ordinal[1]

在使用上,Python的字典又非常像数组,区别在于下标(键)可以是对象而不只是整数。

$ python dictionary

The ordinal array contains {1: 'first', 2: 'second', 3: 'third'} The  ordinal of  1 is  first

Python用对象所关联的方法把打开的文件按对象来处理。顾名思义,readline方法读取一行,所以下面的例子从/etc/passwd文件读取并打印两行内容。

#!/usr/bin/python

f = open('/etc/passwd',  'r')

print f.readline(), print f.readline(), f.close()

$ python fileio

at:x:25:25:Batch jobs  daemon:/var/spool/atjobs:/bin/true bin:x:1:1:bin:/bin:/bin/true

print语句里最后的逗号消除了换行符,因为每行在从原来的文件读入的时候就已经带一个换行符了。

2.5.3 确认输入的例子
下面的脚本片段是Python版的确认输入的程序,我们现在已经很熟悉这个例子了。它展示了子例程和命令行参数的用法,还体现了其他两种Python化的特性。

#!/usr/bin/python import sys

import os

def  show_usage(message, code = 1):

print message

print "%s:  source_dir dest_dir"  % sys.argv[0]

sys.exit(code)

if len(sys.argv) != 3:

show_usage("2 arguments  required; you  supplied %d"  % (len(sys.argv) - 1))

elif  not os.path.isdir(sys.argv[1]):

show_usage("Invalid source directory")

elif  not os.path.isdir(sys.argv[2]):

show_usage("Invalid destination  directory")

source, dest = sys.argv[1:3]

print "Source Directory is", source print "Destination Directory is", dest

除了导入sys模块之外,我们还导入了os模块,从而可以使用os.path.isdir这个例程。注意,对于模块定义的任何代号来说,import命令不会提供访问它们的捷径;必须使用从模块名开始的全名。

例程show_usage的定义里给退出码赋予了一个默认值,万一调用程序没有显式地指定这个参数,就用这个默认值退出。既然所有的数据类型都是对象,所以用引用来给函数传参。

数组sys.argv在第0个位置保存有该脚本的名字,所以它的长度比实际提供的命令行参数个数正好多1。sys.argv[1:3]这样的形式表示一个数组段。有意思的是,数组段不包括指定范围里最后的那个元素,所以这个数组段只有sys.argv[1]和sys.argv[2]两个元素。可以简单地用sys.argv[1:]把从第二个开始的所有元素都包括进来。

同bash和Perl一样,Python也有专门的一种“else if”条件;其关键字是elif。Python也没有case或者switch语句。

给soure和dest变量的平行赋值与Perl有点儿不一样,因为这两个变量本身不在一个列表里。两种形式的平行赋值在Python里都可以。

Python给数值和字符串的比较运算符都一样。“不相等”的比较运算符是!=,但却没有!这样的单目运算符;这样的单目运算符是not。也要搞清楚布尔运算符and和or。

2.5.4 循环
下面的代码片段用一个for…in结构从1循环到10。

for counter  in range(1, 10):

print counter,

和前面例子里的数组段一样,这个范围的右端点实际上没有包括进来。输出值只有1到9。

1 2 3 4 5 6 7 8 9

这是Python里唯一的for循环类型,但它功能很强大。Python的for语句有几项特性,有别于其他语言。

数值范围没有什么特殊之处。任何对象都可以支持Python的循环模型,而且最常见的对象都支持。可以通过一个字符串(按逐个字符)、一个列表、一个文件(按逐个字符、逐行或者逐块),以及一个数组段等。

循环可以产生多个值,循环变量也可以有多个。在每次循环的开头进行的赋值,就和Python正常的多重赋值一样。

for和while循环都可以在末尾加上else子句。只有当循环正常终止之后,才执行这个else子句,这和通过一条break语句退出正好相反。这一功能乍看起来似乎与直觉相反,但它能很好地处理某些用例。

下面的脚本示例接受命令行上的一个正则表达式,把它同一个列表进行匹配,列表里是白雪公主中七个小矮人的名字及其衣服的颜色。该脚本打印第一个匹配的结果,而且匹配正则表达式的部分两边用下划线区分出来。

#!/usr/bin/python import sys

import re

suits = {  'Bashful':'red', 'Sneezy':'green', 'Doc':'blue', 'Dopey':'orange',

'Grumpy':'yellow', 'Happy':'taupe',  'Sleepy':'puce' }

pattern = re.compile("(%s)" % sys.argv[1])

for  dwarf, color in  suits.items():

if pattern.search(dwarf)  or  pattern.search(color):

print "%s's  dwarf suit is  %s." % \

(pattern.sub(r"_\1_",  dwarf), pattern.sub(r"_\1_", color))

break

else:

print "No  dwarves or  dwarf suits matched the pattern."

下面是一些输出的例子:

$ python  dwarfsearch  '[aeiou]{2}'

Sn_ee_zy's dwarf suit is  gr_ee_n.

$ python dwarfsearch go

No  dwarves or  dwarf suits matched the pattern.

给suits赋值的语句,展示了Python用于字典常量的编码方式。suits.items()方法是“键/值”对的迭代器——每次循环都提取一个小矮人的名字和一种衣服颜色。如果只想通过键做循环,只需要把代码写为for dwarf in suits。

Python通过它的re模块实现对正则表达式的处理。Python语言本身没有任何有关正则表达式的功能,所以用Python处理正则表达式比用Perl要稍微麻烦一点儿。在本例中,正则表达式的pattern一开始由compile方法,用圆括号括起来第一个命令行参数进行编译,形成了一个捕获组。接着,用正则表达式对象的search和sub方法测试和修改字符串。还可以像函数那样直接调用re.search等方法,把正则表达式当做第一个参数来用。替换字符串里的\1是反过去引用第一个捕获组的内容。

时间: 2024-12-26 10:38:41

《UNIX/Linux 系统管理技术手册(第四版)》——2.5 Python脚本编程的相关文章

《UNIX/Linux 系统管理技术手册(第四版)》——2.2 bash脚本编程

2.2 bash脚本编程 UNIX/Linux 系统管理技术手册(第四版) bash特别适合编写简单的脚本,用来自动执行那些以往在命令行输入的操作.在命令行用的技巧也能用在bash的脚本里,反之亦然,这让用户在bash上投入的学习时间获得了最大的回报.不过,一旦bash脚本超过了100行,或者需要的特性bash没有,那么就要换到Perl或者Python上了. bash脚本的注释以一个井号(#)开头,并且注释一直延续到行尾.和命令行中一样,可以把逻辑上的一行分成多个物理上的多行来写,每行末尾用反斜

《UNIX/Linux 系统管理技术手册(第四版)》——第2章 脚本和shell 2.1 shell的基础知识

第2章 脚本和shell 好的系统管理员都要写脚本.脚本以标准和自动的方式履行系统管理员的繁杂事务,藉此把管理员的时间节省出来,以花在更重要和更有意思的任务上.从某种意义上讲,脚本也是一种低质量的文档,因为它们充当了一种权威提纲,提纲里列出完成特殊任务所需的步骤. 从复杂性来看,系统管理脚本的范围很广,小到一个脚本,简单得只封装几条静态命令,大到一个重要的软件项目,为整个站点管理主机配置和管理性数据.在本书里,我们所感兴趣的主要是系统管理员通常会碰到的较小的日常脚本项目.因此,对于较大项目才需要

《UNIX/Linux 系统管理技术手册(第四版)》——2.7 推荐读物

2.7 推荐读物 UNIX/Linux 系统管理技术手册(第四版) BROOKS, FREDERICK P., JR. The Mythical Man-Month: Essays on Software Engineer- ing. Reading, MA: Addison-Wesley, 1995. Shell基础知识和bash脚本编程 ALBING, CARL, JP VOSSEN, AND CAMERON NEWHAM.Bash Cookbook. Sebastopol, CA: O'R

《UNIX/Linux 系统管理技术手册(第四版)》——1.2 读者的知识背景

1.2 读者的知识背景 UNIX/Linux 系统管理技术手册(第四版) 本书假定读者已经具备一定程度的Linux或者UNIX经验.尤其要从用户的角度对系统的风格有个一般性的概念,因为我们不再复述这方面的材料.有一些优秀的书籍可以帮助读者迅速掌握这些概念,参见本章1.14节. 即便在现今有三维图形显示功能的桌面计算机上,用于UNIX和Linux系统管理的GUI工具与其下层丰富的软件相比,依然显得相当简单.在现实世界里,我们仍然要通过编辑配置文件和编写脚本来完成管理工作,因此读者需要习惯于使用某种

《UNIX/Linux 系统管理技术手册(第四版)》——2.6 脚本编程的最佳实践

2.6 脚本编程的最佳实践 UNIX/Linux 系统管理技术手册(第四版) 虽然本章里的代码片段几乎不带注释,而且很少打印用法说明,只是因为我们已经列出了每个例子的大纲,从而体现出若干关键点.实际的脚本应该有更好的表现.有几本书通篇就讲编码的最佳实践,不过其中的基本指导原则如下. 如果运行脚本时带了不合适的参数,脚本应该打印一则用法说明,然后再退出.更好的做法是,也以这样的方式实现--help选项. 验证输入的有效性,并检查获得的输入值.例如,在对算出来的一个路径执行rm -fr操作之前,可能

《UNIX/Linux 系统管理技术手册(第四版)》——2.4 Perl编程

2.4 Perl编程 UNIX/Linux 系统管理技术手册(第四版) Larry Wall发明了Perl语言,它第一种真正伟大的脚本编程语言.它的能耐要比bash大得多,而且编写良好的Perl代码也相当容易阅读.另一方面,Perl没有给开发人员强加太多的风格规范,所以不考虑可读性的Perl代码显得很神秘.Perl也被诟病为只适合写(不适合读)的语言. 我们在这里介绍Perl 5,这个版本成为标准已经有10年了.Perl 6是一个仍处在开发之中的主要版本.参考perl6.org了解详情. 对于系

《UNIX/Linux 系统管理技术手册(第四版)》——1.14 推荐读物

1.14 推荐读物 UNIX/Linux 系统管理技术手册(第四版) ROBBINS, ARNOLD. UNIX in a Nutshell (4th Edition). Sebastopol, CA: O'Reilly Me- dia, 2008. SIEVER, ELLEN, AARON WEBER, AND STEPHEN FIGGINS.Linux in a Nutshell (5thEdition). Sebastopol, CA: O'Reilly Media, 2006. GANC

《UNIX/Linux 系统管理技术手册(第四版)》——1.6 特定于系统的管理工具

1.6 特定于系统的管理工具 UNIX/Linux 系统管理技术手册(第四版) 在现代的操作系统内,包含有各种各样可视化的工具和控制面板(比如SUSE的YaST2和IBM的SMIT),帮助用户配置或者管理选定的系统功能.这些工具非常有用,特别是对于管理员新手来说更是如此,但是它们也倾向于不能完整地体现下层软件的实际操作.它们让管理工作变得容易,但大多数又变得不那么权威. 在本书中,出于下面几个原因,我们要介绍可视化工具调用的底层机制,而不是工具本身.第一,可视化工具趋于专有化(或者至少是趋于为系

《UNIX/Linux 系统管理技术手册(第四版)》——第1章 从何处入手 1.1 系统管理员的基本任务

第1章 从何处入手 UNIX/Linux 系统管理技术手册(第四版) 现如今,有关UNIX和Linux的知识太多太多,由手册.博客.期刊.图书以及其他参考资料构成了浩如烟海的知识库,因此,我们在策划本书内容的时候,就从上述的知识库中遴选出沧海一粟,力求专门满足系统管理员的需求. 首先,本书是一本入门培训指南.书中探讨了主要的管理性系统,先区分它们彼此间的不同之处,然后又阐述它们如何协同工作.在很多情况下,同一概念有若干种不同的实现,系统管理员必须要在其中做出自己的选择,我们则介绍每种实现的优缺点

《UNIX/Linux 系统管理技术手册(第四版)》——1.10 其他的权威文档

1.10 其他的权威文档 UNIX/Linux 系统管理技术手册(第四版) 手册页仅仅是官方文档中的很小一部分.遗憾的是,其余更大一部分的文档都散布在Web上. 1.10.1 针对系统的专门指南 大多数发行商都有自己专门的文档项目,许多发行商还出整本书那样的手册.现在,一般都能找到联机形式的手册,而不是纸质的书.文档的规模和质量则大有不同,但是大多数发行商都至少提供一份系统管理指南和一份安装指南.表1.4给出了在哪儿可以找到我们示例系统的文档. 在这其间最出众的是IBM,IBM针对系统管理的各方