python getpass.getuser(),在本地windows调试的时候可以获取到登录的用户

2020-04-23 14:34发布

python 有一个getpass.getuser(),在本地windows调试的时候可以获取到当前登录的用户名,但是部署到服务器之后,就是空的?

python 有一个getpass.getuser(),在本地windows调试的时候可以获取到当前登录的用户名,但是部署到服务器之后,就是空的?

1条回答
曾为
2楼 · 2020-07-16 16:08







                                

                        



PythonStandardLibrary

翻译:Python江湖群

10/06/0720:10:08编译





0.1.关于本书

0.2.代码约定

0.3.关于例子

0.4.如何联系我们


核心模块

1.1.介绍

1.2.__builtin__模块

1.3.exceptions模块

1.4.os模块

1.5.os.path模块

1.6.stat模块

1.7.string模块

1.8.re模块

1.9.math模块

1.10.cmath模块

1.11.operator模块

1.12.copy模块

1.13.sys模块

1.14.atexit模块

1.15.time模块

1.16.types模块

1.17.gc模块


更多标准模块

2.1.概览

2.2.fileinput模块

2.3.shutil模块

2.4.tempfile模块

2.5.StringIO模块

2.6.cStringIO模块

2.7.mmap模块

2.8.UserDict模块

2.9.UserList模块

2.10.UserString模块

2.11.traceback模块

2.12.errno模块

2.13.getopt模块

2.14.getpass模块

2.15.glob模块

2.16.fnmatch模块

2.17.random模块

2.18.whrandom模块

2.19.md5模块

2.20.sha模块

2.21.crypt模块

2.22.rotor模块

2.23.zlib模块

2.24.code模块


线程和进程

3.1.概览

3.2.threading模块

3.3.Queue模块

3.4.thread模块

3.5.commands模块

3.6.pipes模块

3.7.popen2模块

3.8.signal模块


数据表示

4.1.概览

4.2.array模块

4.3.struct模块

4.4.xdrlib模块

4.5.marshal模块

4.6.pickle模块

4.7.cPickle模块

4.8.copy_reg模块

4.9.pprint模块

4.10.repr模块

4.11.base64模块

4.12.binhex模块

4.13.quopri模块

4.14.uu模块

4.15.binascii模块


文件格式

5.1.概览

5.2.xmllib模块

5.3.xml.parsers.expat模块

5.4.sgmllib模块

5.5.htmllib模块

5.6.htmlentitydefs模块

5.7.formatter模块

5.8.ConfigParser模块

5.9.netrc模块

5.10.shlex模块

5.11.zipfile模块

5.12.gzip模块


邮件和新闻消息处理

6.1.概览

6.2.rfc822模块

6.3.mimetools模块

6.4.MimeWriter模块

6.5.mailbox模块

6.6.mailcap模块

6.7.mimetypes模块

6.8.packmail模块

6.9.mimify模块

6.10.multifile模块


网络协议

7.1.概览

7.2.socket模块

7.3.select模块

7.4.asyncore模块

7.5.asynchat模块

7.6.urllib模块

7.7.urlparse模块

7.8.cookie模块

7.9.robotparser模块

7.10.ftplib模块

7.11.gopherlib模块

7.12.httplib模块

7.13.poplib模块

7.14.imaplib模块

7.15.smtplib模块

7.16.telnetlib模块

7.17.nntplib模块

7.18.SocketServer模块

7.19.BaseHTTPServer模块

7.20.SimpleHTTPServer模块

7.21.CGIHTTPServer模块

7.22.cgi模块

7.23.webbrowser模块


国际化

8.1.locale模块

8.2.unicodedata模块

8.3.ucnhash模块


多媒体相关模块

9.1.概览

9.2.imghdr模块

9.3.sndhdr模块

9.4.whatsound模块

9.5.aifc模块

9.6.sunau模块

9.7.sunaudio模块

9.8.wave模块

9.9.audiodev模块

9.10.winsound模块


数据储存

10.1.概览

10.2.anydbm模块

10.3.whichdb模块

10.4.shelve模块

10.5.dbhash模块

10.6.dbm模块

10.7.dumbdbm模块

10.8.gdbm模块


工具和实用程序

11.1.dis模块

11.2.pdb模块

11.3.bdb模块

11.4.profile模块

11.5.pstats模块

11.6.tabnanny模块


其他模块

12.1.概览

12.2.fcntl模块

12.3.pwd模块

12.4.grp模块

12.5.nis模块

12.6.curses模块

12.7.termios模块

12.8.tty模块

12.9.resource模块

12.10.syslog模块

12.11.msvcrt模块

12.12.nt模块

12.13._winreg模块

12.14.posix模块


执行支持模块

13.1.dospath模块

13.2.macpath模块

13.3.ntpath模块

13.4.posixpath模块

13.5.strop模块

13.6.imp模块

13.7.new模块

13.8.pre模块

13.9.sre模块

13.10.py_compile模块

13.11.compileall模块

13.12.ihooks模块

13.13.linecache模块

13.14.macurl2path模块

13.15.nturl2path模块

13.16.tokenize模块

13.17.keyword模块

13.18.parser模块

13.19.symbol模块

13.20.token模块


其他模块

14.1.概览

14.2.pyclbr模块

14.3.filecmp模块

14.4.cmd模块

14.5.rexec模块

14.6.Bastion模块

14.7.readline模块

14.8.rlcompleter模块

14.9.statvfs模块

14.10.calendar模块

14.11.sched模块

14.12.statcache模块

14.13.grep模块

14.14.dircache模块

14.15.dircmp模块

14.16.cmp模块

14.17.cmpcache模块

14.18.util模块

14.19.soundex模块

14.20.timing模块

14.21.posixfile模块

14.22.bisect模块

14.23.knee模块

14.24.tzparse模块

14.25.regex模块

14.26.regsub模块

14.27.reconvert模块

14.28.regex_syntax模块

14.29.find模块


Py2.0后新增模块

后记




"We'dliketopretendthat'Fredrik'isarole,butevenhundredsofvolunteers

couldn'tpossiblykeepup.No,'Fredrik'istheresultofcrossinganhttpserver

withaspamfilterwithanemacswhatsitandsomeotherstuffbesides."


-GordonMcMillan,June1998



Python2.0发布附带了一个包含200个以上模块的可扩展的标准库.

本书简要地介绍每个模块并提供至少一个例子来说明如何使用它.

本书一共包含360个例子.



0.1.关于本书

    

    "ThosepeoplewhohavenothingbettertodothanpostontheInternet

    alldaylongarerarelytheoneswhohavethemostinsights."

    

-JakobNielsen,December1998



五年前我偶然遇到了Python,开始了我的Python之旅,我花费了大量的时间

在comp.lang.python新闻组里回答问题.也许某个人发现一个模块正是他想要的,

但是却不知道如何使用它.也许某个人为他的任务挑选的不合适的模块.也许某个人已经厌

倦了发明新轮子.大多时候,一个简短的例子要比一份手册文档更有帮助.



本书是超过3,000个新闻组讨论的精华部分,当然也有很多的新脚本,为了涵盖标准库的每个角落.



我尽力使得每个脚本都易于理解,易于重用代码.我有意缩短注释的长度,如果你想更深入地

了解背景,那么你可以参阅每个Python发布中的参考手册.本书的重要之处在于范例代码.



我们欢迎任何评论,建议,以及bug报告,请将它们发送到fredrik@pythonware.com.我将阅读尽我所能阅读所有的邮件,但可能回复不是那么及时.



本书的相关更新内容以及其他信息请访问http://www.pythonware.com/people/fredrik/librarybook.htm



为什么没有Tkinter?



本书涵盖了整个标准库,除了(可选的)Tkinterui(user-interface:用户界面)库.有很多原因,

更多是因为时间,本书的空间,以及我正在写另一本关于Tkinter的书.



关于这些书的信息,请访问http://www.pythonware.com/people/fredrik/tkinterbook.htm.(不用看了,又一404)



产品细节



本书使用DocBookSGML编写,我使用了一系列的工具,包括SecretLabs'PythonWorks,

ExcosoftDocumentor,JamesClark'sJadeDSSSLprocessor,NormWalsh'sDocBookstylesheets,

当然,还有一些Python脚本.



感谢帮忙校对的人们:TimPeters,GuidovanRossum,DavidAscher,MarkLutz,和RaelDornfest,

以及PythonWare成员:MatthewEllis,HåkanKarlsson,和RuneUhlin.



感谢LennyMuellner,他帮助我把SGML文件转变为你们现在所看到的这本书,以及ChristienShangraw,

他将那些代码文件集合起来做成了随书CD(可以在http://examples.oreilly.com/pythonsl找到,

竟然没有404,奇迹).



0.2.代码约定


本书使用以下习惯用法:



斜体


    

    用于文件名和命令.还用于定义术语.

    


等宽字体e.g.Python


    

    用于代码以及方法,模块,操作符,函数,语句,属性等的名称.

    


等宽粗体


    

    用于代码执行结果.

    


0.3.关于例子


除非提到,所有例子都可以在Python1.5.2和Python2.0下运行.能不能在Python2.4/2.5下执行.....看参与翻译各位的了.



除了一些平台相关模块的脚本,所有例子都可以在Windows,Solaris,以及Linux下正常执行.



所有代码都是有版权的.当然,你可以自由地使用这些这些模块,别忘记你是从哪得到(?学会)这些的.



大多例子的文件名都包含它所使用的模块名称,后边是"-example-"以及一个唯一的"序号".

注意有些例子并不是按顺序出现的,这是为了匹配本书的较早版本-

(theeff-botguideto)TheStandardPythonLibrary.



你可以在网上找到本书附带CD的内容(参阅http://examples.oreilly.com/pythonsl).更多信息以及更新内容参阅http://www.pythonware.com/people/fredrik/librarybook.htm.(ft,又一404.大家一定不要看~)



0.4.如何联系我们


Python江湖QQ群:43680167



Feather(校对)QQ:85660100




  1. 核心模块

    1. "SincethefunctionsintheCruntimelibraryarenotpartoftheWin32API,

      1. webelievethenumberofapplicationsthatwillbeaffectedbythisbugto

        1. beverylimited."

        2. -Microsoft,January1999

  2. 1.1.介绍

Python的标准库包括了很多的模块,从Python语言自身特定的类型和声明,到一些只用于少数程序的不著名的模块.



本章描述了一些基本的标准库模块.任何大型Python程序都有可能直接或间接地使用到这类模块的大部分.


1.1.1.内建函数和异常


下面的这两个模块比其他模块加在一起还要重要:定义内建函数(例如len,int,range...)的

__builtin__模块,以及定义所有内建异常的exceptions模块.



Python在启动时导入这两个模块,使任何程序都能够使用它们.


1.1.2.操作系统接口模块


Python有许多使用了POSIX标准API和标准C语言库的模块.它们为底层操作系统提供了平台独立的接口.



这类的模块包括:提供文件和进程处理功能的os模块;提供平台独立的文件名处理

(分拆目录名,文件名,后缀等)的os.path模块;以及时间日期处理相关的time/datetime模块.


[!Feather注:datetime为Py2.3新增模块,提供增强的时间处理方法]


延伸一点说,网络和线程模块同样也可以归为这一个类型.不过Python并没有在所有的平台/版本实现这些.


1.1.3.类型支持模块


标准库里有许多用于支持内建类型操作的库.string模块实现了常用的字符串处理.

math模块提供了数学计算操作和常量(pi,e都属于这类常量),cmath模块为复数提供了和

math一样的功能.


1.1.4.正则表达式


re模块为Python提供了正则表达式支持.正则表达式是用于匹配字符串或特定子字符串的

有特定语法的字符串模式.


1.1.5.语言支持模块


sys模块可以让你访问解释器相关参数,比如模块搜索路径,解释器版本号等.

operator模块提供了和内建操作符作用相同的函数.copy模块允许

你复制对象,Python2.0新加入的gc模块提供了对垃圾收集的相关控制功能.




1.2.__builtin__模块


这个模块包含Python中使用的内建函数.一般不用手动导入这个模块;Python会帮你做好一切.


1.2.1.使用元组或字典中的参数调用函数


Python允许你实时地创建函数参数列表.只要把所有的参数放入一个元组中,

然后通过内建的apply函数调用函数.如Example1-1.



1.2.1.1.Example1-1.使用apply函数

File:builtin-apply-example-1.pydeffunction(a,b):printa,bapply(function,("whither","canada?"))apply(function,(1,2+3))whithercanada?15


要想把关键字参数传递给一个函数,你可以将一个字典作为apply函数的第3个参数,

参考Example1-2.



1.2.1.2.Example1-2.使用apply函数传递关键字参数

File:builtin-apply-example-2.pydeffunction(a,b):printa,bapply(function,("crunchy","frog"))apply(function,("crunchy",),{"b":"frog"})apply(function,(),{"a":"crunchy","b":"frog"})crunchyfrogcrunchyfrogcrunchyfrog


apply函数的一个常见用法是把构造函数参数从子类传递到基类,

尤其是构造函数需要接受很多参数的时候.如Example1-3所示.



1.2.1.3.Example1-3.使用apply函数调用基类的构造函数

File:builtin-apply-example-3.pyclassRectangle:def__init__(self,color="white",width=10,height=10):print"createa",color,self,"sized",width,"x",heightclassRoundedRectangle(Rectangle):def__init__(self,**kw):apply(Rectangle.__init__,(self,),kw)rect=Rectangle(color="green",height=100,width=100)rect=RoundedRectangle(color="blue",height=20)createagreensized100x100createabluesized10x20


Python2.0提供了另个方法来做相同的事.你只需要使用一个传统的函数调用,

使用*来标记元组,**来标记字典.



下面两个语句是等价的:


result=function(*args,**kwargs)result=apply(function,args,kwargs)

1.2.2.加载和重载模块


如果你写过较庞大的Python程序,那么你就应该知道import语句是用来导入外部模块的

(当然也可以使用from-import版本).不过你可能不知道import其实是靠调用内建

函数__import__来工作的.



通过这个戏法你可以动态地调用函数.当你只知道模块名称(字符串)的时候,这将很方便.

Example1-4展示了这种用法,动态地导入所有以"-plugin"结尾的模块.



1.2.2.1.Example1-4.使用__import__函数加载模块

File:builtin-import-example-1.pyimportglob,osmodules=[]formodule_fileinglob.glob("*-plugin.py"):try:module_name,ext=os.path.splitext(os.path.basename(module_file))module=__import__(module_name)modules.append(module)exceptImportError:pass#ignorebrokenmodules#sayhellotoallmodulesformoduleinmodules:module.hello()example-pluginsayshello


注意这个plug-in模块文件名中有个"-"(hyphens).这意味着你不能使用普通的import命令,因为Python的辨识符不允许有"-".



Example1-5展示了Example1-4中使用的plug-in.



1.2.2.2.Example1-5.Plug-in例子

File:example-plugin.pydefhello():print"example-pluginsayshello"


Example1-6展示了如何根据给定模块名和函数名获得想要的函数对象.



1.2.2.3.Example1-6.使用__import__函数获得特定函数

File:builtin-import-example-2.pydefgetfunctionbyname(module_name,function_name):module=__import__(module_name)returngetattr(module,function_name)printrepr(getfunctionbyname("dumbdbm","open"))


你也可以使用这个函数实现延迟化的模块导入(lazymoduleloading).例如在Example1-7中

的string模块只在第一次使用的时候导入.



1.2.2.4.Example1-7.使用__import__函数实现延迟导入

File:builtin-import-example-3.pyclassLazyImport:def__init__(self,module_name):self.module_name=module_nameself.module=Nonedef__getattr__(self,name):ifself.moduleisNone:self.module=__import__(self.module_name)returngetattr(self.module,name)string=LazyImport("string")printstring.lowercaseabcdefghijklmnopqrstuvwxyz


Python也提供了重新加载已加载模块的基本支持.[Example1-8#eg-1-8会加载3次hello.py文件.



1.2.2.5.Example1-8.使用reload函数

File:builtin-reload-example-1.pyimporthelloreload(hello)reload(hello)helloagain,andwelcometotheshowhelloagain,andwelcometotheshowhelloagain,andwelcometotheshow


reload直接接受模块作为参数.


[!Feather注:^原句无法理解,稍后讨论.]


注意,当你重加载模块时,它会被重新编译,新的模块会代替模块字典里的老模块.但是,已经用原模块里的类建立的实例仍然使用的是老模块(不会被更新).



同样地,使用from-import直接创建的到模块内容的引用也是不会被更新的.


1.2.3.关于名称空间


dir返回由给定模块,类,实例,或其他类型的所有成员组成的列表.这可能在交互式Python解释器下很有用,也可以用在其他地方.Example1-9展示了dir函数的用法.



1.2.3.1.Example1-9.使用dir函数

File:builtin-dir-example-1.pydefdump(value):printvalue,"=>",dir(value)importsysdump(0)dump(1.0)dump(0.0j)#complexnumberdump([])#listdump({})#dictionarydump("string")dump(len)#functiondump(sys)#module0=>[]1.0=>[]0j=>['conjugate','imag','real'][]=>['append','count','extend','index','insert','pop','remove','reverse','sort']{}=>['clear','copy','get','has_key','items','keys','update','values']string=>[]=>['__doc__','__name__','__self__']=>['__doc__','__name__','__stderr__','__stdin__','__stdout__','argv','builtin_module_names','copyright','dllhandle','exc_info','exc_type','exec_prefix','executable',...


在例子Example1-10中定义的getmember函数返回给定类定义的所有类级别的属性和方法.



1.2.3.2.Example1-10.使用dir函数查找类的所有成员

File:builtin-dir-example-2.pyclassA:defa(self):passdefb(self):passclassB(A):defc(self):passdefd(self):passdefgetmembers(klass,members=None):#getalistofallclassmembers,orderedbyclassifmembersisNone:members=[]forkinklass.__bases__:getmembers(k,members)formindir(klass):ifmnotinmembers:members.append(m)returnmembersprintgetmembers(A)printgetmembers(B)printgetmembers(IOError)['__doc__','__module__','a','b']['__doc__','__module__','a','b','c','d']['__doc__','__getitem__','__init__','__module__','__str__']


getmembers函数返回了一个有序列表.成员在列表中名称出现的越早,

它所处的类层次就越高.如果无所谓顺序的话,你可以使用字典代替列表.


[!Feather注:字典是无序的,而列表和元组是有序的,网上有关于有序字典的讨论]


vars函数与此相似,它返回的是包含每个成员当前值的字典.如果你使用不带参数的vars,它将返回当前局部名称空间的可见元素(同locals()函数).如Example1-11所表示.



1.2.3.3.Example1-11.使用vars函数

File:builtin-vars-example-1.pybook="library2"pages=250scripts=350print"the%(book)sbookcontainsmorethan%(scripts)sscripts"%vars()thelibrarybookcontainsmorethan350scripts

1.2.4.检查对象类型


Python是一种动态类型语言,这意味着给一个定变量名可以在不同的场合绑定到不同的类型上.在接下面例子中,同样的函数分别被整数,浮点数,以及一个字符串调用:


deffunction(value):printvaluefunction(1)function(1.0)function("one")


type函数(如Example1-12所示)允许你检查一个变量的类型.这个函数会返回一个

typedescriptor(类型描述符),它对于Python解释器提供的每个类型都是不同的.



1.2.4.1.Example1-12.使用type函数

File:builtin-type-example-1.pydefdump(value):printtype(value),valuedump(1)dump(1.0)dump("one")11.0one


每个类型都有一个对应的类型对象,所以你可以使用is操作符(对象身份?)来

检查类型.(如Example1-13所示).



1.2.4.2.Example1-13.对文件名和文件对象使用type函数

File:builtin-type-example-2.pydefload(file):ifisinstance(file,type("")):file=open(file,"rb")returnfile.read()printlen(load("samples/sample.jpg")),"bytes"printlen(load(open("samples/sample.jpg","rb"))),"bytes"4672bytes4672bytes


callable函数,如Example1-14所示,可以检查一个对象是否是可调用的

(无论是直接调用或是通过apply).对于函数,方法,lambda函式,类,

以及实现了__call__方法的类实例,它都返回True.



1.2.4.3.Example1-14.使用callable函数

File:builtin-callable-example-1.pydefdump(function):ifcallable(function):printfunction,"iscallable"else:printfunction,"is*not*callable"classA:defmethod(self,value):returnvalueclassB(A):def__call__(self,value):returnvaluea=A()b=B()dump(0)#simpleobjectsdump("string")dump(callable)dump(dump)#functiondump(A)#classesdump(B)dump(B.method)dump(a)#instancesdump(b)dump(b.method)0is*not*callablestringis*not*callableiscallableiscallableAiscallableBiscallableiscallableis*not*callableiscallableiscallable


注意类对象(A和B)都是可调用的;如果调用它们,就产生新的对象(类实例).但是A类的实例不可调用,因为它的类没有实现__call__方法.



你可以在operator模块中找到检查对象是否为某一内建类型(数字,序列,或者字典等)

的函数.但是,因为创建一个类很简单(比如实现基本序列方法的类),所以对这些

类型使用显式的类型判断并不是好主意.



在处理类和实例的时候会复杂些.Python不会把类作为本质上的类型对待;相反地,所有的类都属于一个特殊的类类型(specialclasstype),所有的类实例属于一个特殊的实例类型(specialinstancetype).



这意味着你不能使用type函数来测试一个实例是否属于一个给定的类;所有的实例都是同样

的类型!为了解决这个问题,你可以使用isinstance函数,它会检查一个对象是

不是给定类(或其子类)的实例.Example1-15展示了isinstance函数的使用.



1.2.4.4.Example1-15.使用isinstance函数

File:builtin-isinstance-example-1.pyclassA:passclassB:passclassC(A):passclassD(A,B):passdefdump(object):printobject,"=>",ifisinstance(object,A):print"A",ifisinstance(object,B):print"B",ifisinstance(object,C):print"C",ifisinstance(object,D):print"D",printa=A()b=B()c=C()d=D()dump(a)dump(b)dump(c)dump(d)dump(0)dump("string")=>A=>B=>AC=>ABD0=>string=>


issubclass函数与此相似,它用于检查一个类对象是否与给定类相同,

或者是给定类的子类.如Example1-16所示.



注意,isinstance可以接受任何对象作为参数,而issubclass函数在接受非类对象参

数时会引发TypeError异常.



1.2.4.5.Example1-16.使用issubclass函数

File:builtin-issubclass-example-1.pyclassA:passclassB:passclassC(A):passclassD(A,B):passdefdump(object):printobject,"=>",ifissubclass(object,A):print"A",ifissubclass(object,B):print"B",ifissubclass(object,C):print"C",ifissubclass(object,D):print"D",printdump(A)dump(B)dump(C)dump(D)dump(0)dump("string")A=>AB=>BC=>ACD=>ABD0=>Traceback(innermostlast):File"builtin-issubclass-example-1.py",line29,in?File"builtin-issubclass-example-1.py",line15,indumpTypeError:argumentsmustbeclasses

1.2.5.计算Python表达式


Python提供了在程序中与解释器交互的多种方法.例如eval函数将一个字符串

作为Python表达式求值.你可以传递一串文本,简单的表达式,或者使用

内建Python函数.如Example1-17所示.



1.2.5.1.Example1-17.使用eval函数

File:builtin-eval-example-1.pydefdump(expression):result=eval(expression)printexpression,"=>",result,type(result)dump("1")dump("1.0")dump("'string'")dump("1.0+2.0")dump("'*'*10")dump("len('world')")1=>11.0=>1.0'string'=>string1.0+2.0=>3.0'*'*10=>**********len('world')=>5


如果你不确定字符串来源的安全性,那么你在使用eval的时候会遇到些麻烦.例如,

某个用户可能会使用__import__函数加载os模块,然后从硬盘删除文件

(如Example1-18所示).



1.2.5.2.Example1-18.使用eval函数执行任意命令

File:builtin-eval-example-2.pyprinteval("__import__('os').getcwd()")printeval("__import__('os').remove('file')")/home/fredrik/librarybookTraceback(innermostlast):File"builtin-eval-example-2",line2,in?File"",line0,in?os.error:(2,'Nosuchfileordirectory')


这里我们得到了一个os.error异常,这说明Python事实上在尝试删除文件!



幸运地是,这个问题很容易解决.你可以给eval函数传递第2

个参数,一个定义了该表达式求值时名称空间的字典.

我们测试下,给函数传递个空字典:


>>>printeval("__import__('os').remove('file')",{})Traceback(innermostlast):File"",line1,in?File"",line0,in?os.error:(2,'Nosuchfileordirectory')


呃....我们还是得到了个os.error异常.



这是因为Python在求值前会检查这个字典,如果没有发现名称为__builtins__

的变量(复数形式),它就会添加一个:


>>>namespace={}>>>printeval("__import__('os').remove('file')",namespace)Traceback(innermostlast):File"",line1,in?File"",line0,in?os.error:(2,'Nosuchfileordirectory')>>>namespace.keys()['__builtins__']


如果你打印这个namespace的内容,你会发现里边有所有的内建函数.


[!Feather注:如果我RP不错的话,添加的这个__builtins__就是当前的__builtins__]


我们注意到了如果这个变量存在,Python就不会去添加默认的,那么我们的解决方法也来了,

为传递的字典参数加入一个__builtins__项即可.如Example1-19所示.



1.2.5.3.Example1-19.安全地使用eval函数求值

File:builtin-eval-example-3.pyprinteval("__import__('os').getcwd()",{})printeval("__import__('os').remove('file')",{"__builtins__":{}})/home/fredrik/librarybookTraceback(innermostlast):File"builtin-eval-example-3.py",line2,in?File"",line0,in?NameError:__import__


即使这样,你仍然无法避免针对CPU和内存资源的攻击.(比如,形如

eval("'*'*1000000*2*2*2*2*2*2*2*2*2")的语句在执行后会使你的程序耗尽系统资源).


1.2.6.编译和执行代码


eval函数只针对简单的表达式.如果要处理大块的代码,你应该使用compile和exec函数

(如Example1-20所示).



1.2.6.1.Example1-20.使用compile函数检查语法

File:builtin-compile-example-1.pyNAME="script.py"BODY="""prnt'owl-stretchingtime'"""try:compile(BODY,NAME,"exec")exceptSyntaxError,v:print"syntaxerror:",v,"in",NAME#syntaxerror:invalidsyntaxinscript.py


成功执行后,compile函数会返回一个代码对象,你可以使用exec语句执行它,

参见Example1-21.



1.2.6.2.Example1-21.执行已编译的代码

File:builtin-compile-example-2.pyBODY="""print'theant,anintroduction'"""code=compile(BODY,"[removed]","exec")printcodeexeccodetheant,anintroduction


使用Example1-22中的类可以在程序执行时实时地生成代码.write方法用于添加代码,

indent和dedent方法用于控制缩进结构.其他部分交给类来处理.



1.2.6.3.Example1-22.简单的代码生成工具

File:builtin-compile-example-3.pyimportsys,stringclassCodeGeneratorBackend:"SimplecodegeneratorforPython"defbegin(self,tab="/t"):self.code=[]self.tab=tabself.level=0defend(self):self.code.append("")#makesurethere'sanewlineattheendreturncompile(string.join(self.code,"/n"),"","exec")defwrite(self,string):self.code.append(self.tab*self.level+string)defindent(self):self.level=self.level+1#in2.0andlater,thiscanbewrittenas:self.level+=1defdedent(self):ifself.level==0:raiseSyntaxError,"internalerrorincodegenerator"self.level=self.level-1#or:self.level-=1##tryitout!c=CodeGeneratorBackend()c.begin()c.write("foriinrange(5):")c.indent()c.write("print'codegenerationmadeeasy!'")c.dedent()execc.end()codegenerationmadeeasy!codegenerationmadeeasy!codegenerationmadeeasy!codegenerationmadeeasy!codegenerationmadeeasy!


Python还提供了execfile函数,一个从文件加载代码,编译代码,执行代码的快捷方式.

Example1-23简单地展示了如何使用这个函数.



1.2.6.4.Example1-23.使用execfile函数

File:builtin-execfile-example-1.pyexecfile("hello.py")defEXECFILE(filename,locals=None,globals=None):execcompile(open(filename).read(),filename,"exec")inlocals,globalsEXECFILE("hello.py")helloagain,andwelcometotheshowhelloagain,andwelcometotheshow


Example1-24中的代码是Example1-23中使用的hello.py文件.



1.2.6.5.Example1-24.hello.py脚本

File:hello.pyprint"helloagain,andwelcometotheshow"

1.2.7.从__builtin__模块重载函数


因为Python在检查局部名称空间和模块名称空间前不会检查内建函数,所以有时候你可能要显式地引用

__builtin__模块.例如Example1-25重载了内建的open函数.

这时候要想使用原来的open函数,就需要脚本显式地指明模块名称.



1.2.7.1.Example1-25.显式地访问__builtin__模块中的函数

File:builtin-open-example-1.pydefopen(filename,mode="rb"):import__builtin__file=__builtin__.open(filename,mode)iffile.read(5)notin("GIF87","GIF89"):raiseIOError,"notaGIFfile"file.seek(0)returnfilefp=open("samples/sample.gif")printlen(fp.read()),"bytes"fp=open("samples/sample.jpg")printlen(fp.read()),"bytes"3565bytesTraceback(innermostlast):File"builtin-open-example-1.py",line12,in?File"builtin-open-example-1.py",line5,inopenIOError:notaGIFfile

[!Feather注:明白这个open()函数是干什么的么?检查一个文件是否是GIF文件,一般如这类的图片格式都在文件开头有默认的格式.另外打开文件推荐使用file()而不是open(),虽然暂时没有区别]



1.3.exceptions模块


exceptions模块提供了标准异常的层次结构.Python启动的时候会自动导入这个模块,

并且将它加入到__builtin__模块中.也就是说,一般不需要手动导入这个模块.



在1.5.2版本时它是一个普通模块,2.0以及以后版本成为内建模块.



该模块定义了以下标准异常:


Exception是所有异常的基类.强烈建议(但不是必须)自定义的异常异常也继承这个类.

SystemExit(Exception)由sys.exit函数引发.如果它在最顶层没有被try-except语句捕获,

那么解释器将直接关闭而不会显示任何跟踪返回信息.

StandardError(Exception)是所有内建异常的基类(除SystemExit外).

KeyboardInterrupt(StandardError)在用户按下Control-C(或其他打断按键)后被引发.如果它可能会在你使用"捕获所有"的try-except语句时导致奇怪的问题.

ImportError(StandardError)在Python导入模块失败时被引发.

EnvironmentError作为所有解释器环境引发异常的基类.(也就是说,这些异常一般不是由于程序bug引起).

IOError(EnvironmentError)用于标记I/O相关错误.

OSError(EnvironmentError)用于标记os模块引起的错误.

WindowsError(OSError)用于标记os模块中Windows相关错误.

NameError(StandardError)在Python查找全局或局部名称失败时被引发.

UnboundLocalError(NameError),当一个局部变量还没有赋值就被使用时,会引发这个异常.这个异常只有在2.0及之后的版本有;早期版本只会引发一个普通的NameError.

AttributeError(StandardError),当Python寻找(或赋值)给一个实例属性,方法,模块功能或其它有效的命名失败时,会引发这个异常.

SyntaxError(StandardError),当解释器在编译时遇到语法错误,这个异常就被引发.

(2.0及以后版本)IndentationError(SyntaxError)在遇到非法的缩进时被引发.该异常只用于2.0及以后版本,之前版本会引发一个SyntaxError异常.

(2.0及以后版本)TabError(IndentationError),当使用-tt选项检查不一致缩进时有可能被引发.该异常只用于2.0及以后版本,之前版本会引发一个SyntaxError异常.

TypeError(StandardError),当给定类型的对象不支持一个操作时被引发.

AssertionError(StandardError)在assert语句失败时被引发(即表达式为false时).

LookupError(StandardError)作为序列或字典没有包含给定索引或键时所引发异常的基类.

IndexError(LookupError),当序列对象使用给定索引数索引失败时(不存在索引对应对象)引发该异常.

KeyError(LookupError)当字典对象使用给定索引索引失败时(不存在索引对应对象)引发该异常.

ArithmeticError(StandardError)作为数学计算相关异常的基类.

OverflowError(ArithmeticError)在操作溢出时被引发(例如当一个整数太大,导致不能符合给定类型).

ZeroDivisionError(ArithmeticError),当你尝试用0除某个数时被引发.

FloatingPointError(ArithmeticError),当浮点数操作失败时被引发.

ValueError(StandardError),当一个参数类型正确但值不合法时被引发.

(2.0及以后版本)UnicodeError(ValueError),Unicode字符串类型相关异常.只使用在2.0及以后版本.

RuntimeError(StandardError),当出现运行时问题时引发,包括在限制模式下尝试访问外部内容,未知的硬件问题等等.

NotImplementedError(RuntimeError),用于标记未实现的函数,或无效的方法.

SystemError(StandardError),解释器内部错误.该异常值会包含更多的细节

(经常会是一些深层次的东西,比如"eval_code2:NULLglobals").

这本书的作者编了5年程序都没见过这个错误.(想必是没有用raiseSystemError).

MemoryError(StandardError),当解释器耗尽内存时会引发该异常.注意只有在底层内存分配抱怨时这个异常才会发生;如果是在你的旧机器上,这个异常发生之前系统会陷入混乱的内存交换中.



你可以创建自己的异常类.只需要继承内建的Exception类(或者它的任意一个合适的子类)即可,有需要时可以再重载它的__str__方法.Example1-26展示了如何使用exceptions模块.



1.3.0.1.Example1-26.使用exceptions模块

File:exceptions-example-1.py#pythonimportsthismodulebyitself,sothefollowing#lineisn'treallyneeded#python会自动导入该模块,所以以下这行是不必要的#importexceptionsclassHTTPError(Exception):#indicatesanHTTPprotocolerrordef__init__(self,url,errcode,errmsg):self.url=urlself.errcode=errcodeself.errmsg=errmsgdef__str__(self):return(""%(self.url,self.errcode,self.errmsg))try:raiseHTTPError("",error.urlprint"errcode","=>",error.errcodeprint"errmsg","=>",error.errmsgraise#reraiseexceptionurl=>http://www.python.org/fooerrcode=>200errmsg=>NotFoundTraceback(innermostlast):File"exceptions-example-1",line16,in?HTTPError:">http://www.python.org/foo",200,"NotFound")exceptHTTPError,error:print"url","=>",error.urlprint"errcode","=>",error.errcodeprint"errmsg","=>",error.errmsgraise#reraiseexceptionurl=>http://www.python.org/fooerrcode=>200errmsg=>NotFoundTraceback(innermostlast):File"exceptions-example-1",line16,in?HTTPError:



1.4.os模块


这个模块中的大部分函数通过对应平台相关模块实现,比如posix和

nt.os模块会在第一次导入的时候自动加载合适的执行模块.


1.4.1.处理文件


内建的open/file函数用于创建,打开和编辑文件,如Example1-27所示.而

os模块提供了重命名和删除文件所需的函数.



1.4.1.1.Example1-27.使用os模块重命名和删除文件

File:os-example-3.pyimportosimportstringdefreplace(file,search_for,replace_with):#replacestringsinatextfileback=os.path.splitext(file)[0]+".bak"temp=os.path.splitext(file)[0]+".tmp"try:#removeoldtempfile,ifanyos.remove(temp)exceptos.error:passfi=open(file)fo=open(temp,"w")forsinfi.readlines():fo.write(string.replace(s,search_for,replace_with))fi.close()fo.close()try:#removeoldbackupfile,ifanyos.remove(back)exceptos.error:pass#renameoriginaltobackup...os.rename(file,back)#...andtemporarytooriginalos.rename(temp,file)##tryitout!file="samples/sample.txt"replace(file,"hello","tjena")replace(file,"tjena","hello")

1.4.2.处理目录


os模块也包含了一些用于目录处理的函数.



listdir函数返回给定目录中所有文件名(包括目录名)组成的列表,如

Example1-28所示.而Unix和Windows中使用的当前目录和父目录标记(.和..)不包含在此列表中.



1.4.2.1.Example1-28.使用os列出目录下的文件

File:os-example-5.pyimportosforfileinos.listdir("samples"):printfilesample.ausample.jpgsample.wav...


getcwd和chdir函数分别用于获得和改变当前工作目录.如Example1-29所示.



1.4.2.2.Example1-29.使用os模块改变当前工作目录

File:os-example-4.pyimportos#wherearewe?cwd=os.getcwd()print"1",cwd#godownos.chdir("samples")print"2",os.getcwd()#gobackupos.chdir(os.pardir)print"3",os.getcwd()1/ematter/librarybook2/ematter/librarybook/samples3/ematter/librarybook


makedirs和removedirs函数用于创建或删除目录层,如Example1-30所示.



1.4.2.3.Example1-30.使用os模块创建/删除多个目录级

File:os-example-6.pyimportosos.makedirs("test/multiple/levels")fp=open("test/multiple/levels/file","w")fp.write("inspectorpraline")fp.close()#removethefileos.remove("test/multiple/levels/file")#andallemptydirectoriesaboveitos.removedirs("test/multiple/levels")


removedirs函数会删除所给路径中最后一个目录下所有的空目录.

而mkdir和rmdir函数只能处理单个目录级.如Example1-31所示.



1.4.2.4.Example1-31.使用os模块创建/删除目录

File:os-example-7.pyimportosos.mkdir("test")os.rmdir("test")os.rmdir("samples")#thiswillfailTraceback(innermostlast):File"os-example-7",line6,in?OSError:[Errno41]Directorynotempty:'samples'


如果需要删除非空目录,你可以使用shutil模块中的rmtree函数.


1.4.3.处理文件属性


stat函数可以用来获取一个存在文件的信息,如Example1-32

所示.它返回一个类元组对象(stat_result对象,包含10个元素),

依次是st_mode(权限模式),st_ino(inodenumber),st_dev(device),

st_nlink(numberofhardlinks),st_uid(所有者用户ID),st_gid

(所有者所在组ID),st_size(文件大小,字节),st_atime(最近一次访问时间),

st_mtime(最近修改时间),st_ctime(平台相关;Unix下的最近一次元数据/metadata修改时间,

或者Windows下的创建时间)-以上项目也可作为属性访问.


[!Feather注:原文为9元元组.另,返回对象并非元组类型,为struct.]


1.4.3.1.Example1-32.使用os模块获取文件属性

File:os-example-1.pyimportosimporttimefile="samples/sample.jpg"defdump(st):mode,ino,dev,nlink,uid,gid,size,atime,mtime,ctime=stprint"-size:",size,"bytes"print"-owner:",uid,gidprint"-created:",time.ctime(ctime)print"-lastaccessed:",time.ctime(atime)print"-lastmodified:",time.ctime(mtime)print"-mode:",oct(mode)print"-inode/dev:",ino,dev##getstatsforafilenamest=os.stat(file)print"stat",filedump(st)print##getstatsforanopenfilefp=open(file)st=os.fstat(fp.fileno())print"fstat",filedump(st)statsamples/sample.jpg-size:4762bytes-owner:00-created:TueSep0722:45:581999-lastaccessed:SunSep1900:00:001999-lastmodified:SunMay1901:42:161996-mode:0100666-inode/dev:02fstatsamples/sample.jpg-size:4762bytes-owner:00-created:TueSep0722:45:581999-lastaccessed:SunSep1900:00:001999-lastmodified:SunMay1901:42:161996-mode:0100666-inode/dev:00


返回对象中有些属性在非Unix平台下是无意义的,比如(st_inode,st_dev)为

Unix下的为每个文件提供了唯一标识,但在其他平台可能为任意无意义数据.



stat模块包含了很多可以处理该返回对象的常量及函数.下面的代码展示了其中的一些.



可以使用chmod和utime函数修改文件的权限模式和时间属性,如Example1-33所示.



1.4.3.2.Example1-33.使用os模块修改文件的权限和时间戳

File:os-example-2.pyimportosimportstat,timeinfile="samples/sample.jpg"outfile="out.jpg"#copycontentsfi=open(infile,"rb")fo=open(outfile,"wb")while1:s=fi.read(10000)ifnots:breakfo.write(s)fi.close()fo.close()#copymodeandtimestampst=os.stat(infile)os.chmod(outfile,stat.S_IMODE(st[stat.ST_MODE]))os.utime(outfile,(st[stat.ST_ATIME],st[stat.ST_MTIME]))print"original","=>"print"mode",oct(stat.S_IMODE(st[stat.ST_MODE]))print"atime",time.ctime(st[stat.ST_ATIME])print"mtime",time.ctime(st[stat.ST_MTIME])print"copy","=>"st=os.stat(outfile)print"mode",oct(stat.S_IMODE(st[stat.ST_MODE]))print"atime",time.ctime(st[stat.ST_ATIME])print"mtime",time.ctime(st[stat.ST_MTIME])original=>mode0666atimeThuOct1415:15:501999mtimeMonNov1315:42:361995copy=>mode0666atimeThuOct1415:15:501999mtimeMonNov1315:42:361995

1.4.4.处理进程


system函数在当前进程下执行一个新命令,并等待它完成,如Example1-34所示.



1.4.4.1.Example1-34.使用os执行操作系统命令

File:os-example-8.pyimportosifos.name=="nt":command="dir"else:command="ls-l"os.system(command)-rwxrw-r--1effboteffbot76Oct914:17README-rwxrw-r--1effboteffbot1727Oct719:00SimpleAsyncHTTP.py-rwxrw-r--1effboteffbot314Oct720:29aifc-example-1.py-rwxrw-r--1effboteffbot259Oct720:38anydbm-example-1.py...


命令通过操作系统的标准shell执行,并返回shell的退出状态.需要注意的是在Windows95/98

下,shell通常是command.com,它的推出状态总是0.


    

    由于11os.system11直接将命令传递给shell,所以如果你不检查传入参数的时候会很危险

    (比如命令os.system("viewer%s"%file),将file变量设置为

    "sample.jpg;rm-rf$HOME"....).如果不确定参数的安全性,那么最好使用

    exec或spawn代替(稍后介绍).

    


exec函数会使用新进程替换当前进程(或者说是"转到进程").在Example1-35中,

字符串"goodbye"永远不会被打印.



1.4.4.2.Example1-35.使用os模块启动新进程

File:os-exec-example-1.pyimportosimportsysprogram="python"arguments=["hello.py"]printos.execvp(program,(program,)+tuple(arguments))print"goodbye"helloagain,andwelcometotheshow


Python提供了很多表现不同的exec函数.Example1-35使用的是

execvp函数,它会从标准路径搜索执行程序,把第二个参数(元组)作为单独的参数传递给程序,并使用当前的环境变量来运行程序.其他七个同类型函数请参阅PythonLibraryReference.



在Unix环境下,你可以通过组合使用exec,fork以及wait函数来从当前程序调用另一个程序,

如Example1-36所示.fork函数复制当前进程,wait函数会等待一个子进程执行结束.



1.4.4.3.Example1-36.使用os模块调用其他程序(Unix)

File:os-exec-example-2.pyimportosimportsysdefrun(program,*args):pid=os.fork()ifnotpid:os.execvp(program,(program,)+args)returnos.wait()[0]run("python","hello.py")print"goodbye"helloagain,andwelcometotheshowgoodbye


fork函数在子进程返回中返回0(这个进程首先从fork返回值),

在父进程中返回一个非0的进程标识符(子进程的PID).也就是说,

只有当我们处于子进程的时候"notpid"才为真.



fork和wait函数在Windows上是不可用的,但是你可以使用spawn函数,

如Example1-37所示.不过,spawn不会沿着路径搜索可执行文件,

你必须自己处理好这些.



1.4.4.4.Example1-37.使用os模块调用其他程序(Windows)

File:os-spawn-example-1.pyimportosimportstringdefrun(program,*args):#findexecutableforpathinstring.split(os.environ["PATH"],os.pathsep):file=os.path.join(path,program)+".exe"try:returnos.spawnv(os.P_WAIT,file,(file,)+args)exceptos.error:passraiseos.error,"cannotfindexecutable"run("python","hello.py")print"goodbye"helloagain,andwelcometotheshowgoodbye


spawn函数还可用于在后台运行一个程序.Example1-38给run函数添加了一个可选的

mode参数;当设置为os.P_NOWAIT时,这个脚本不会等待子程序结束,

默认值os.P_WAIT时spawn会等待子进程结束.



其它的标志常量还有os.P_OVERLAY,它使得spawn的行为和exec类似,

以及os.P_DETACH,它在后台运行子进程,与当前控制台和键盘焦点隔离.



1.4.4.5.Example1-38.使用os模块在后台执行程序(Windows)

File:os-spawn-example-2.pyimportosimportstringdefrun(program,*args,**kw):#findexecutablemode=kw.get("mode",os.P_WAIT)forpathinstring.split(os.environ["PATH"],os.pathsep):file=os.path.join(path,program)+".exe"try:returnos.spawnv(mode,file,(file,)+args)exceptos.error:passraiseos.error,"cannotfindexecutable"run("python","hello.py",mode=os.P_NOWAIT)print"goodbye"goodbyehelloagain,andwelcometotheshow


Example1-39提供了一个在Unix和Windows平台上通用的spawn方法.



1.4.4.6.Example1-39.使用spawn或fork/exec调用其他程序

File:os-spawn-example-3.pyimportosimportstringifos.namein("nt","dos"):exefile=".exe"else:exefile=""defspawn(program,*args):try:#possible2.0shortcut!returnos.spawnvp(program,(program,)+args)exceptAttributeError:passtry:spawnv=os.spawnvexceptAttributeError:#assumeit'sunixpid=os.fork()ifnotpid:os.execvp(program,(program,)+args)returnos.wait()[0]else:#gotspawnvbutnospawnp:golookforanexecutableforpathinstring.split(os.environ["PATH"],os.pathsep):file=os.path.join(path,program)+exefiletry:returnspawnv(os.P_WAIT,file,(file,)+args)exceptos.error:passraiseIOError,"cannotfindexecutable"##tryitout!spawn("python","hello.py")print"goodbye"helloagain,andwelcometotheshowgoodbye


Example1-39首先尝试调用spawnvp函数.如果该函数不存在

(一些版本/平台没有这个函数),它将继续查找一个名为spawnv的函数并且

开始查找程序路径.作为最后的选择,它会调用exec和fork函数完成工作.


1.4.5.处理守护进程(DaemonProcesses)


Unix系统中,你可以使用fork函数把当前进程转入后台(一个"守护者/daemon").一般来说,你需要派生(forkoff)一个当前进程的副本,然后终止原进程,如Example1-40所示.



1.4.5.1.Example1-40.使用os模块使脚本作为守护执行(Unix)

File:os-example-14.pyimportosimporttimepid=os.fork()ifpid:os._exit(0)#killoriginalprint"daemonstarted"time.sleep(10)print"daemonterminated"


需要创建一个真正的后台程序稍微有点复杂,首先调用setpgrp函数创建一个"进程组首领/processgroupleader".否则,向无关进程组发送的信号(同时)会引起守护进程的问题:


os.setpgrp()


为了确保守护进程创建的文件能够获得程序指定的modeflags(权限模式标记?),最好删除usermodemask:


os.umask(0)


然后,你应该重定向stdout/stderr文件,而不能只是简单地关闭它们(如果你的程序需要stdout

或stderr写入内容的时候,可能会出现意想不到的问题).


classNullDevice:defwrite(self,s):passsys.stdin.close()sys.stdout=NullDevice()sys.stderr=NullDevice()


换言之,由于Python的print和C中的printf/fprintf在设备(device)

没有连接后不会关闭你的程序,此时守护进程中的sys.stdout.write()会抛出一个IOError异常,而你的程序依然在后台运行的很好....



另外,先前例子中的_exit函数会终止当前进程.而sys.exit不同,如果调用者(caller)

捕获了SystemExit异常,程序仍然会继续执行.如Example1-41所示.



1.4.5.2.Example1-41.使用os模块终止当前进程

File:os-example-9.pyimportosimportsystry:sys.exit(1)exceptSystemExit,value:print"caughtexit(%s)"%valuetry:os._exit(2)exceptSystemExit,value:print"caughtexit(%s)"%valueprint"bye!"caughtexit(1)



1.5.os.path模块


os.path模块包含了各种处理长文件名(路径名)的函数.先导入(import)os

模块,然后就可以以os.path访问该模块.


1.5.1.处理文件名


os.path模块包含了许多与平台无关的处理长文件名的函数.

也就是说,你不需要处理前后斜杠,冒号等.我们可以看看Example1-42中的样例代码.



1.5.1.1.Example1-42.使用os.path模块处理文件名

File:os-path-example-1.pyimportosfilename="my/little/pony"print"using",os.name,"..."print"split","=>",os.path.split(filename)print"splitext","=>",os.path.splitext(filename)print"dirname","=>",os.path.dirname(filename)print"basename","=>",os.path.basename(filename)print"join","=>",os.path.join(os.path.dirname(filename),os.path.basename(filename))usingnt...split=>('my/little','pony')splitext=>('my/little/pony','')dirname=>my/littlebasename=>ponyjoin=>my/little/pony


注意这里的split只分割出最后一项(不带斜杠).



os.path模块中还有许多函数允许你简单快速地获知文件名的一些特征,如Example1-43所示。



1.5.1.2.Example1-43.使用os.path模块检查文件名的特征

File:os-path-example-2.pyimportosFILES=(os.curdir,"/","file","/file","samples","samples/sample.jpg","directory/file","../directory/file","/directory/file")forfileinFILES:printfile,"=>",ifos.path.exists(file):print"EXISTS",ifos.path.isabs(file):print"ISABS",ifos.path.isdir(file):print"ISDIR",ifos.path.isfile(file):print"ISFILE",ifos.path.islink(file):print"ISLINK",ifos.path.ismount(file):print"ISMOUNT",print.=>EXISTSISDIR/=>EXISTSISABSISDIRISMOUNTfile=>/file=>ISABSsamples=>EXISTSISDIRsamples/sample.jpg=>EXISTSISFILEdirectory/file=>../directory/file=>/directory/file=>ISABS


expanduser函数以与大部分Unixshell相同的方式处理用户名快捷符号(~,

不过在Windows下工作不正常),如Example1-44所示.



1.5.1.3.Example1-44.使用os.path模块将用户名插入到文件名

File:os-path-expanduser-example-1.pyimportosprintos.path.expanduser("~/.pythonrc")#/home/effbot/.pythonrc


expandvars函数将文件名中的环境变量替换为对应值,如Example1-45所示.



1.5.1.4.Example1-45.使用os.path替换文件名中的环境变量

File:os-path-expandvars-example-1.pyimportosos.environ["USER"]="user"printos.path.expandvars("/home/$USER/config")printos.path.expandvars("$USER/folders")/home/user/configuser/folders

1.5.2.搜索文件系统


walk函数会帮你找出一个目录树下的所有文件(如Example1-46

所示).它的参数依次是目录名,回调函数,以及传递给回调函数的数据对象.



1.5.2.1.Example1-46.使用os.path搜索文件系统

File:os-path-walk-example-1.pyimportosdefcallback(arg,directory,files):forfileinfiles:printos.path.join(directory,file),repr(arg)os.path.walk(".",callback,"secretmessage")./aifc-example-1.py'secretmessage'./anydbm-example-1.py'secretmessage'./array-example-1.py'secretmessage'..../samples'secretmessage'./samples/sample.jpg'secretmessage'./samples/sample.txt'secretmessage'./samples/sample.zip'secretmessage'./samples/articles'secretmessage'./samples/articles/article-1.txt'secretmessage'./samples/articles/article-2.txt'secretmessage'...


walk函数的接口多少有点晦涩(也许只是对我个人而言,我总是记不住参数的顺序).

Example1-47中展示的index函数会返回一个文件名列表,

你可以直接使用for-in循环处理文件.



1.5.2.2.Example1-47.使用os.listdir搜索文件系统

File:os-path-walk-example-2.pyimportosdefindex(directory):#likeos.listdir,buttraversesdirectorytreesstack=[directory]files=[]whilestack:directory=stack.pop()forfileinos.listdir(directory):fullname=os.path.join(directory,file)files.append(fullname)ifos.path.isdir(fullname)andnotos.path.islink(fullname):stack.append(fullname)returnfilesforfileinindex("."):printfile./aifc-example-1.py./anydbm-example-1.py./array-example-1.py...


如果你不想列出所有的文件(基于性能或者是内存的考虑),Example1-48展示了另一种方法.

这里DirectoryWalker类的行为与序列对象相似,一次返回一个文件.(generator?)



1.5.2.3.Example1-48.使用DirectoryWalker搜索文件系统

File:os-path-walk-example-3.pyimportosclassDirectoryWalker:#aforwarditeratorthattraversesadirectorytreedef__init__(self,directory):self.stack=[directory]self.files=[]self.index=0def__getitem__(self,index):while1:try:file=self.files[self.index]self.index=self.index+1exceptIndexError:#popnextdirectoryfromstackself.directory=self.stack.pop()self.files=os.listdir(self.directory)self.index=0else:#gotafilenamefullname=os.path.join(self.directory,file)ifos.path.isdir(fullname)andnotos.path.islink(fullname):self.stack.append(fullname)returnfullnameforfileinDirectoryWalker("."):printfile./aifc-example-1.py./anydbm-example-1.py./array-example-1.py...


注意DirectoryWalker类并不检查传递给__getitem__方法的索引值.

这意味着如果你越界访问序列成员(索引数字过大)的话,这个类将不能正常工作.



最后,如果你需要处理文件大小和时间戳,Example1-49给出了一个类,

它返回文件名和它的os.stat属性(一个元组).这个版本在每个文件上都能节省一次或两次

stat调用(os.path.isdir和os.path.islink内部都使用了stat),

并且在一些平台上运行很快.



1.5.2.4.Example1-49.使用DirectoryStatWalker搜索文件系统

File:os-path-walk-example-4.pyimportos,statclassDirectoryStatWalker:#aforwarditeratorthattraversesadirectorytree,and#returnsthefilenameandadditionalfileinformationdef__init__(self,directory):self.stack=[directory]self.files=[]self.index=0def__getitem__(self,index):while1:try:file=self.files[self.index]self.index=self.index+1exceptIndexError:#popnextdirectoryfromstackself.directory=self.stack.pop()self.files=os.listdir(self.directory)self.index=0else:#gotafilenamefullname=os.path.join(self.directory,file)st=os.stat(fullname)mode=st[stat.ST_MODE]ifstat.S_ISDIR(mode)andnotstat.S_ISLNK(mode):self.stack.append(fullname)returnfullname,stforfile,stinDirectoryStatWalker("."):printfile,st[stat.ST_SIZE]./aifc-example-1.py336./anydbm-example-1.py244./array-example-1.py526



1.6.stat模块


Example1-50展示了stat模块的基本用法,

这个模块包含了一些os.stat函数中可用的常量和测试函数.



1.6.0.1.Example1-50.UsingthestatModule

File:stat-example-1.pyimportstatimportos,timest=os.stat("samples/sample.txt")print"mode","=>",oct(stat.S_IMODE(st[stat.ST_MODE]))print"type","=>",ifstat.S_ISDIR(st[stat.ST_MODE]):print"DIRECTORY",ifstat.S_ISREG(st[stat.ST_MODE]):print"REGULAR",ifstat.S_ISLNK(st[stat.ST_MODE]):print"LINK",printprint"size","=>",st[stat.ST_SIZE]print"lastaccessed","=>",time.ctime(st[stat.ST_ATIME])print"lastmodified","=>",time.ctime(st[stat.ST_MTIME])print"inodechanged","=>",time.ctime(st[stat.ST_CTIME])mode=>0664type=>REGULARsize=>305lastaccessed=>SunOct1022:12:301999lastmodified=>SunOct1018:39:371999inodechanged=>SunOct1015:26:381999



1.7.string模块


string模块提供了一些用于处理字符串类型的函数,

如Example1-51所示.



1.7.0.1.Example1-51.使用string模块

File:string-example-1.pyimportstringtext="MontyPython'sFlyingCircus"print"upper","=>",string.upper(text)print"lower","=>",string.lower(text)print"split","=>",string.split(text)print"join","=>",string.join(string.split(text),"+")print"replace","=>",string.replace(text,"Python","Java")print"find","=>",string.find(text,"Python"),string.find(text,"Java")print"count","=>",string.count(text,"n")upper=>MONTYPYTHON'SFLYINGCIRCUSlower=>montypython'sflyingcircussplit=>['Monty',"Python's",'Flying','Circus']join=>Monty+Python's+Flying+Circusreplace=>MontyJava'sFlyingCircusfind=>6-1count=>3


在Python1.5.2以及更早版本中,string使用strop中的函数来实现模块功能.



在Python1.6和后继版本,更多的字符串操作都可以作为字符串方法来访问,

如Example1-52所示,string模块中的许多函数只是对相对应字符串方法的封装.



1.7.0.2.Example1-52.使用字符串方法替代string模块函数

File:string-example-2.pytext="MontyPython'sFlyingCircus"print"upper","=>",text.upper()print"lower","=>",text.lower()print"split","=>",text.split()print"join","=>","+".join(text.split())print"replace","=>",text.replace("Python","Perl")print"find","=>",text.find("Python"),text.find("Perl")print"count","=>",text.count("n")upper=>MONTYPYTHON'SFLYINGCIRCUSlower=>montypython'sflyingcircussplit=>['Monty',"Python's",'Flying','Circus']join=>Monty+Python's+Flying+Circusreplace=>MontyPerl'sFlyingCircusfind=>6-1count=>3


为了增强模块对字符的处理能力,除了字符串方法,string

模块还包含了类型转换函数用于把字符串转换为其他类型,(如Example1-53所示).



1.7.0.3.Example1-53.使用string模块将字符串转为数字

File:string-example-3.pyimportstringprintint("4711"),printstring.atoi("4711"),printstring.atoi("11147",8),#octal八进制printstring.atoi("1267",16),#hexadecimal十六进制printstring.atoi("3mv",36)#whatever...printstring.atoi("4711",0),printstring.atoi("04711",0),printstring.atoi("0x4711",0)printfloat("4711"),printstring.atof("1"),printstring.atof("1.23e5")4711471147114711471147112505181934711.01.0123000.0


大多数情况下(特别是当你使用的是1.6及更高版本时),你可以使用int和float

函数代替string模块中对应的函数。



atoi函数可以接受可选的第二个参数,指定数基(numberbase).

如果数基为0,那么函数将检查字符串的前几个字符来决定使用的数基:

如果为"0x,"数基将为16(十六进制),如果为"0,"则数基为8(八进制).

默认数基值为10(十进制),当你未传递参数时就使用这个值.



在1.6及以后版本中,int函数和atoi一样可以接受第二个参数.

与字符串版本函数不一样的是,int和float可以接受Unicode字符串对象.




1.8.re模块

    

    "Somepeople,whenconfrontedwithaproblem,think'Iknow,I'lluseregularexpressions.'Nowtheyhavetwoproblems."

    

-JamieZawinski,oncomp.lang.emacs



re模块提供了一系列功能强大的正则表达式(regularexpression)工具,

它们允许你快速检查给定字符串是否与给定的模式匹配(使用match函数),

或者包含这个模式(使用search函数).正则表达式是以紧凑(也很神秘)的语法写出的字符串模式.



match尝试从字符串的起始匹配一个模式,如Example1-54所示.

如果模式匹配了某些内容(包括空字符串,如果模式允许的话),

它将返回一个匹配对象.使用它的group方法可以找出匹配的内容.



1.8.0.1.Example1-54.使用re模块来匹配字符串

File:re-example-1.pyimportretext="TheAttilatheHunShow"#asinglecharacter单个字符m=re.match(".",text)ifm:printrepr("."),"=>",repr(m.group(0))#anystringofcharacters任何字符串m=re.match(".*",text)ifm:printrepr(".*"),"=>",repr(m.group(0))#astringofletters(atleastone)只包含字母的字符串(至少一个)m=re.match("/w+",text)ifm:printrepr("/w+"),"=>",repr(m.group(0))#astringofdigits只包含数字的字符串m=re.match("/d+",text)ifm:printrepr("/d+"),"=>",repr(m.group(0))'.'=>'T''.*'=>'TheAttilatheHunShow''//w+'=>'The'


可以使用圆括号在模式中标记区域.找到匹配后,group方法可以抽取这些区域的内容,

如Example1-55所示.group(1)会返回第一组的内容,group(2)

返回第二组的内容,这样...如果你传递多个组数给group函数,它会返回一个元组.



1.8.0.2.Example1-55.使用re模块抽出匹配的子字符串

File:re-example-2.pyimportretext="10/15/99"m=re.match("(/d{2})/(/d{2})/(/d{2,4})",text)ifm:printm.group(1,2,3)('10','15','99')


search函数会在字符串内查找模式匹配,如Example1-56所示.

它在所有可能的字符位置尝试匹配模式,从最左边开始,一旦找到匹配就返回一个匹配对象.

如果没有找到相应的匹配,就返回None.



1.8.0.3.Example1-56.使用re模块搜索子字符串

File:re-example-3.pyimportretext="Example3:Thereis1date10/25/95inhere!"m=re.search("(/d{1,2})/(/d{1,2})/(/d{2,4})",text)printm.group(1),m.group(2),m.group(3)month,day,year=m.group(1,2,3)printmonth,day,yeardate=m.group(0)printdate10259510259510/25/95


Example1-57中展示了sub函数,它可以使用另个字符串替代匹配模式.



1.8.0.4.Example1-57.使用re模块替换子字符串

File:re-example-4.pyimportretext="you'renofunanymore..."#literalreplace(string.replaceisfaster)#文字替换(string.replace速度更快)printre.sub("fun","entertaining",text)#collapseallnon-lettersequencestoasingledash#将所有非字母序列转换为一个"-"(dansh,破折号)printre.sub("[^/w]+","-",text)#convertallwordstobeeps#将所有单词替换为BEEPprintre.sub("/S+","-BEEP-",text)you'renoentertaininganymore...you-re-no-fun-anymore--BEEP--BEEP--BEEP--BEEP-


你也可以通过回调(callback)函数使用sub来替换指定模式.

Example1-58展示了如何预编译模式.



1.8.0.5.Example1-58.使用re模块替换字符串(通过回调函数)

File:re-example-5.pyimportreimportstringtext="alineoftext//012anotherlineoftext//012etc..."defoctal(match):#replaceoctalcodewithcorrespondingASCIIcharacter#使用对应ASCII字符替换八进制代码returnchr(string.atoi(match.group(1),8))octal_pattern=re.compile(r"//(/d/d/d)")printtextprintoctal_pattern.sub(octal,text)alineoftext/012anotherlineoftext/012etc...alineoftextanotherlineoftextetc...


如果你不编译,re模块会为你缓存一个编译后版本,所有的小脚本中,

通常不需要编译正则表达式.Python1.5.2中,缓存中可以容纳20个匹配模式,而在2.0中,

缓存则可以容纳100个匹配模式.



最后,Example1-59用一个模式列表匹配一个字符串.这些模式将会组合为一个模式,并预编译以节省时间.



1.8.0.6.Example1-59.使用re模块匹配多个模式中的一个

File:re-example-6.pyimportre,stringdefcombined_pattern(patterns):p=re.compile(string.join(map(lambdax:"("+x+")",patterns),"|"))deffixup(v,m=p.match,r=range(0,len(patterns))):try:regs=m(v).regsexceptAttributeError:returnNone#nomatch,som.regswillfailelse:foriinr:ifregs[i+1]!=(-1,-1):returnireturnfixup##tryitout!patterns=[r"/d+",r"abc/d{2,4}",r"p/w+"]p=combined_pattern(patterns)printp("129391")printp("abc800")printp("abc1600")printp("python")printp("perl")printp("tcl")01122None



1.9.math模块


math模块实现了许多对浮点数的数学运算函数.这些函数一般是对平台C

库中同名函数的简单封装,所以一般情况下,不同平台下计算的结果可能稍微地有所不同,

有时候甚至有很大出入.Example1-60展示了如何使用math模块.



1.9.0.1.Example1-60.使用math模块

File:math-example-1.pyimportmathprint"e","=>",math.eprint"pi","=>",math.piprint"hypot","=>",math.hypot(3.0,4.0)#andmanyothers...e=>2.71828182846pi=>3.14159265359hypot=>5.0


完整函数列表请参阅PythonLibraryReference.




1.10.cmath模块


Example1-61所展示的cmath模块包含了一些用于复数运算的函数.



1.10.0.1.Example1-61.使用cmath模块

File:cmath-example-1.pyimportcmathprint"pi","=>",cmath.piprint"sqrt(-1)","=>",cmath.sqrt(-1)pi=>3.14159265359sqrt(-1)=>1j


完整函数列表请参阅PythonLibraryReference.




1.11.operator模块


operator模块为Python提供了一个"功能性"的标准操作符接口.当使用map以及

filter一类的函数的时候,operator模块中的函数可以替换一些lambda函式.

而且这些函数在一些喜欢写晦涩代码的程序员中很流行.Example1-62展示了

operator模块的一般用法.



1.11.0.1.Example1-62.使用operator模块

File:operator-example-1.pyimportoperatorsequence=1,2,4print"add","=>",reduce(operator.add,sequence)print"sub","=>",reduce(operator.sub,sequence)print"mul","=>",reduce(operator.mul,sequence)print"concat","=>",operator.concat("spam","egg")print"repeat","=>",operator.repeat("spam",5)print"getitem","=>",operator.getitem(sequence,2)print"indexOf","=>",operator.indexOf(sequence,2)print"sequenceIncludes","=>",operator.sequenceIncludes(sequence,3)add=>7sub=>-5mul=>8concat=>spameggrepeat=>spamspamspamspamspamgetitem=>4indexOf=>1sequenceIncludes=>0


Example1-63展示了一些可以用于检查对象类型的operator函数.



1.11.0.2.Example1-63.使用operator模块检查类型

File:operator-example-2.pyimportoperatorimportUserListdefdump(data):printtype(data),"=>",ifoperator.isCallable(data):print"CALLABLE",ifoperator.isMappingType(data):print"MAPPING",ifoperator.isNumberType(data):print"NUMBER",ifoperator.isSequenceType(data):print"SEQUENCE",printdump(0)dump("string")dump("string"[0])dump([1,2,3])dump((1,2,3))dump({"a":1})dump(len)#function函数dump(UserList)#module模块dump(UserList.UserList)#class类dump(UserList.UserList())#instance实例=>NUMBER=>SEQUENCE=>SEQUENCE=>SEQUENCE=>SEQUENCE=>MAPPING=>CALLABLE=>=>CALLABLE=>MAPPINGNUMBERSEQUENCE


这里需要注意operator模块使用非常规的方法处理对象实例.所以使用

isNumberType,isMappingType,以及isSequenceType函数的时候要小心,

这很容易降低代码的扩展性.



同样需要注意的是一个字符串序列成员(单个字符)也是序列.所以当在递归函数使用isSequenceType来截断对象树的时候,别把普通字符串作为参数(或者是任何包含字符串的序列对象).




1.12.copy模块


copy模块包含两个函数,用来拷贝对象,如Example1-64所示.



copy(object)=>object创建给定对象的"浅/浅层(shallow)"拷贝(copy).这里

"浅/浅层(shallow)"的意思是复制对象本身,但当对象是一个容器(container)时,

它的成员仍然指向原来的成员对象.



1.12.0.1.Example1-64.使用copy模块复制对象

File:copy-example-1.pyimportcopya=[[1],[2],[3]]b=copy.copy(a)print"before","=>"printaprintb#modifyoriginala[0][0]=0a[1]=Noneprint"after","=>"printaprintbbefore=>[[1],[2],[3]][[1],[2],[3]]after=>[[0],None,[3]][[0],[2],[3]]


你也可以使用[:]语句(完整切片)来对列表进行浅层复制,也可以使用copy方法复制字典.



相反地,deepcopy(object)=>object创建一个对象的深层拷贝(deepcopy),

如Example1-65所示,当对象为一个容器时,所有的成员都被递归地复制了。



1.12.0.2.Example1-65.使用copy模块复制集合(Collections)

File:copy-example-2.pyimportcopya=[[1],[2],[3]]b=copy.deepcopy(a)print"before","=>"printaprintb#modifyoriginala[0][0]=0a[1]=Noneprint"after","=>"printaprintbbefore=>[[1],[2],[3]][[1],[2],[3]]after=>[[0],None,[3]][[1],[2],[3]]



1.13.sys模块


sys模块提供了许多函数和变量来处理Python运行时环境的不同部分.


1.13.1.处理命令行参数


在解释器启动后,argv列表包含了传递给脚本的所有参数,如Example1-66所示.

列表的第一个元素为脚本自身的名称.



1.13.1.1.Example1-66.使用sys模块获得脚本的参数

File:sys-argv-example-1.pyimportsysprint"scriptnameis",sys.argv[0]iflen(sys.argv)>1:print"thereare",len(sys.argv)-1,"arguments:"forarginsys.argv[1:]:printargelse:print"therearenoarguments!"scriptnameissys-argv-example-1.pytherearenoarguments!


如果是从标准输入读入脚本(比如"python

脚本的名称将被设置为空串.如果把脚本作为字符串传递给python(使用-c选项),

脚本名会被设置为"-c".


1.13.2.处理模块


path列表是一个由目录名构成的列表,Python从中查找扩展模块(Python源模块,编译模块,或者二进制扩展).

启动Python时,这个列表从根据内建规则,PYTHONPATH环境变量的内容,以及注册表(Windows系统)等进行初始化.

由于它只是一个普通的列表,你可以在程序中对它进行操作,如Example1-67所示.



1.13.2.1.Example1-67.使用sys模块操作模块搜索路径

File:sys-path-example-1.pyimportsysprint"pathhas",len(sys.path),"members"#addthesampledirectorytothepathsys.path.insert(0,"samples")importsample#nukethepathsys.path=[]importrandom#oops!pathhas7membersthisisthesamplemodule!Traceback(innermostlast):File"sys-path-example-1.py",line11,in?importrandom#oops!ImportError:Nomodulenamedrandom


builtin_module_names列表包含Python解释器中所有内建模块的名称,Example1-68

给出了它的样例代码.



1.13.2.2.Example1-68.使用sys模块查找内建模块

File:sys-builtin-module-names-example-1.pyimportsysdefdump(module):printmodule,"=>",ifmoduleinsys.builtin_module_names:print""else:module=__import__(module)printmodule.__file__dump("os")dump("sys")dump("string")dump("strop")dump("zlib")os=>C:/python/lib/os.pycsys=>string=>C:/python/lib/string.pycstrop=>zlib=>C:/python/zlib.pyd


modules字典包含所有加载的模块.import语句在从磁盘导入内容之前会先检查这个字典.



正如你在Example1-69中所见到的,Python在处理你的脚本之前就已经导入了很多模块.



1.13.2.3.Example1-69.使用sys模块查找已导入的模块

File:sys-modules-example-1.pyimportsysprintsys.modules.keys()['os.path','os','exceptions','__main__','ntpath','strop','nt','sys','__builtin__','site','signal','UserDict','string','stat']

1.13.3.处理引用记数


getrefcount函数(如Example1-70所示)返回给定对象的引用记数-

也就是这个对象使用次数.Python会跟踪这个值,当它减少为0的时候,就销毁这个对象.



1.13.3.1.Example1-70.使用sys模块获得引用记数

File:sys-getrefcount-example-1.pyimportsysvariable=1234printsys.getrefcount(0)printsys.getrefcount(variable)printsys.getrefcount(None)503192


注意这个值总是比实际的数量大,因为该函数本身在确定这个值的时候依赖这个对象.



==检查主机平台===



Example1-71展示了platform变量,它包含主机平台的名称.



1.13.3.2.Example1-71.使用sys模块获得当前平台

File:sys-platform-example-1.pyimportsys##emulate"importos.path"(sortof)...ifsys.platform=="win32":importntpathpathmodule=ntpathelifsys.platform=="mac":importmacpathpathmodule=macpathelse:#assumeit'saposixplatformimportposixpathpathmodule=posixpathprintpathmodule


典型的平台有Windows9X/NT(显示为win32),以及Macintosh(显示为mac).

对于Unix系统而言,platform通常来自"uname-r"命令的输出,例如irix6,linux2,

或者sunos5(Solaris).


1.13.4.跟踪程序


setprofiler函数允许你配置一个分析函数(profilingfunction).

这个函数会在每次调用某个函数或方法时被调用(明确或隐含的),

或是遇到异常的时候被调用.让我们看看Example1-72的代码.



1.13.4.1.Example1-72.使用sys模块配置分析函数

File:sys-setprofiler-example-1.pyimportsysdeftest(n):j=0foriinrange(n):j=j+ireturnndefprofiler(frame,event,arg):printevent,frame.f_code.co_name,frame.f_lineno,"->",arg#profilerisactivatedonthenextcall,return,orexception#分析函数将在下次函数调用,返回,或异常时激活sys.setprofile(profiler)#profilethisfunctioncall#分析这次函数调用test(1)#disableprofiler#禁用分析函数sys.setprofile(None)#don'tprofilethiscall#不会分析这次函数调用test(2)calltest3->Nonereturntest7->1


基于该函数,profile模块提供了一个完整的分析器框架.



Example1-73中的settrace函数与此类似,

但是trace函数会在解释器每执行到新的一行时被调用.



1.13.4.2.Example1-73.使用sys模块配置单步跟踪函数

File:sys-settrace-example-1.pyimportsysdeftest(n):j=0foriinrange(n):j=j+ireturnndeftracer(frame,event,arg):printevent,frame.f_code.co_name,frame.f_lineno,"->",argreturntracer#tracerisactivatedonthenextcall,return,orexception#跟踪器将在下次函数调用,返回,或异常时激活sys.settrace(tracer)#tracethisfunctioncall#跟踪这次函数调用test(1)#disabletracing#禁用跟踪器sys.settrace(None)#don'ttracethiscall#不会跟踪这次函数调用test(2)calltest3->Nonelinetest3->Nonelinetest4->Nonelinetest5->Nonelinetest5->Nonelinetest6->Nonelinetest5->Nonelinetest7->Nonereturntest7->1


基于该函数提供的跟踪功能,pdb模块提供了完整的调试(debug)框架.


1.13.5.处理标准输出/输入


stdin,stdout,以及stderr变量包含与标准I/O流对应的流对象.

如果需要更好地控制输出,而print不能满足你的要求,它们就是你所需要的.

你也可以替换它们,这时候你就可以重定向输出和输入到其它设备(device),

或者以非标准的方式处理它们.如Example1-74所示.



1.13.5.1.Example1-74.使用sys重定向输出

File:sys-stdout-example-1.pyimportsysimportstringclassRedirect:def__init__(self,stdout):self.stdout=stdoutdefwrite(self,s):self.stdout.write(string.lower(s))#redirectstandardoutput(includingtheprintstatement)#重定向标准输出(包括print语句)old_stdout=sys.stdoutsys.stdout=Redirect(sys.stdout)print"HEJASVERIGE",print"FRISKTHUM/303/226R"#restorestandardoutput#恢复标准输出sys.stdout=old_stdoutprint"M/303/205/303/205/303/205/303/205L!"hejasverigefriskthum/303/266rM/303/205/303/205/303/205/303/205L!


要重定向输出只要创建一个对象,并实现它的write方法.



(除非C类型的实例外:Python使用一个叫做softspace的整数属性来控制输出中的空白.

如果没有这个属性,Python将把这个属性附加到这个对象上.你不需要在使用Python对象时担心,

但是在重定向到一个C类型时,你应该确保该类型支持softspace属性.)


1.13.6.退出程序


执行至主程序的末尾时,解释器会自动退出.但是如果需要中途退出程序,你可以调用sys.exit函数,

它带有一个可选的整数参数返回给调用它的程序.Example1-75给出了范例.



1.13.6.1.Example1-75.使用sys模块退出程序

File:sys-exit-example-1.pyimportsysprint"hello"sys.exit(1)print"there"hello


注意sys.exit并不是立即退出.而是引发一个SystemExit异常.

这意味着你可以在主程序中捕获对sys.exit的调用,如Example1-76所示.



1.13.6.2.Example1-76.捕获sys.exit调用

File:sys-exit-example-2.pyimportsysprint"hello"try:sys.exit(1)exceptSystemExit:passprint"there"hellothere


如果准备在退出前自己清理一些东西(比如删除临时文件),你可以配置一个

"退出处理函数"(exithandler),它将在程序退出的时候自动被调用.如Example1-77所示.



1.13.6.3.Example1-77.另一种捕获sys.exit调用的方法

File:sys-exitfunc-example-1.pyimportsysdefexitfunc():print"world"sys.exitfunc=exitfuncprint"hello"sys.exit(1)print"there"#neverprinted#不会被printhelloworld


在Python2.0以后,你可以使用atexit

相关问题推荐

  • 回答 3

    换行。比如,print hello\nworld效果就是helloworld\n就是一个换行符。\是转义的意思,'\n'是换行,'\t'是tab,'\\'是,\ 是在编写程序中句子太长百,人为换行后加上\但print出来是一整行。...

  • 回答 42

    十种常见排序算法一般分为以下几种:(1)非线性时间比较类排序:a. 交换类排序(快速排序、冒泡排序)b. 插入类排序(简单插入排序、希尔排序)c. 选择类排序(简单选择排序、堆排序)d. 归并排序(二路归并排序、多路归并排序)(2)线性时间非比较类排序:...

  • 回答 70
    已采纳

    前景很好,中国正在产业升级,工业机器人和人工智能方面都会是强烈的热点,而且正好是在3~5年以后的时间。难度,肯定高,要求你有创新的思维能力,高数中的微积分、数列等等必须得非常好,软件编程(基础的应用最广泛的语言:C/C++)必须得很好,微电子(数字电...

  • 回答 28

    迭代器与生成器的区别:(1)生成器:生成器本质上就是一个函数,它记住了上一次返回时在函数体中的位置。对生成器函数的第二次(或第n次)调用,跳转到函数上一次挂起的位置。而且记录了程序执行的上下文。生成器不仅记住了它的数据状态,生成器还记住了程序...

  • 回答 9

    python中title( )属于python中字符串函数,返回’标题化‘的字符串,就是单词的开头为大写,其余为小写

  • 回答 6

    第一种解释:代码中的cnt是count的简称,一种电脑计算机内部的数学函数的名字,在Excel办公软件中计算参数列表中的数字项的个数;在数据库( sq| server或者access )中可以用来统计符合条件的数据条数。函数COUNT在计数时,将把数值型的数字计算进去;但是...

  • 回答 1

    head是方法,所以需要取小括号,即dataset.head()显示的则是前5行。data[:, :-1]和data[:, -1]。另外,如果想通过位置取数据,请使用iloc,即dataset.iloc[:, :-1]和dataset.iloc[:, -1],前者表示的是取所有行,但不包括最后一列的数据,结果是个DataFrame。...

  • Python入门简单吗2021-09-23 13:21
    回答 45

    挺简单的,其实课程内容没有我们想象的那么难、像我之前同学,完全零基础,培训了半年,直接出来就工作了,人家还在北京大公司上班,一个月15k,实力老厉害了

  • 回答 4

    Python针对众多的类型,提供了众多的内建函数来处理(内建是相对于导入import来说的,后面学习到包package时,将会介绍),这些内建函数功用在于其往往可对多种类型对象进行类似的操作,即多种类型对象的共有的操作;如果某种操作只对特殊的某一类对象可行,Pyt...

  • 回答 8

     相当于 ... 这里不是注释

  • 回答 4

    还有FIXME

  • 回答 3

    python的两个库:xlrd和xlutils。 xlrd打开excel,但是打开的excel并不能直接写入数据,需要用xlutils主要是复制一份出来,实现后续的写入功能。

  • 回答 8

    单行注释:Python中的单行注释一般是以#开头的,#右边的文字都会被当做解释说明的内容,不会被当做执行的程序。为了保证代码的可读性,一般会在#后面加一两个空格然后在编写解释内容。示例:#  单行注释print(hello world)注释可以放在代码上面也可以放在代...

  • 回答 2

    主要是按行读取,然后就是写出判断逻辑来勘测行是否为注视行,空行,编码行其他的:import linecachefile=open('3_2.txt','r')linecount=len(file.readlines())linecache.getline('3_2.txt',linecount)这样做的过程中发现一个问题,...

  • 回答 4

    或许是里面有没被注释的代码

  • 回答 26

    自学的话要看个人情况,可以先在B站找一下视频看一下

没有解决我的问题,去提问