在python中有多种运行外部程序的方法,比如,运行操作系统命令或另外的python脚本,或执行一个磁盘上的文件,或通过网络来运行文件
在特定执行场景包括:
在当前脚本继续运行
创建和管理子进程
执行外部命令或程序
执行需要输入的命令
通过网络来调用命令
执行命令来创建需要处理的输出
执行其他python脚本
执行一系列动态生成的Python语句
导入Python模块
Python中,内建和外部模块都可以提供上述功能,程序员得根据实现的需要,从这些模块中选择合适的处理方法
14.1 可调用对象
即任何能够通过函数操作符"()"来调用的对象,函数操作符得紧跟在可调用对象之后,比如,用"foo()"来调用函数"foo"
14.1.1 函数
内建函数(BIFs):
BIF是用c/c++写的,编译过后放入python解释器,然后把他们作为第一(内建)名字空间的一部分加载进系统
BIF 属性描述
bif.__doc__文档字符串(或None)
bif.__name__字符串类型的文档名字
bif.__self__设置为None(保留给built-in方法)
bif.__module__存放bif定义的模块名字(或None)
用dir()流出函数的所有属性:
>>> dir(type)
['__abstractmethods__', '__base__', '__bases__', '__basicsize__', '__call__', '__class__', '__delattr__', '__dict__', '__dictoffset__', '__doc__', '__eq__', '__flags__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__instancecheck__', '__itemsize__', '__le__', '__lt__', '__module__', '__mro__', '__name__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasscheck__', '__subclasses__', '__subclasshook__', '__weakrefoffset__', 'mro']
>>> type(dir)
<type 'builtin_function_or_method'>
>>> type(int)
<type 'type'>
>>> type(type)
<type 'type'>
用户定义的函数(UDF)
UDF属性描述
udf.__doc__文档字符串(也可以用udf.func_doc)
udf.__name__字符串类型的函数名字(也可以用udf.func_name)
udf.func_code字节编译的代码对象
udf.func_defaults默认的参数元祖
udf.func_globals全局名字空间字典:和从函数内部调用globals(x)一样
udf.func_dict函数属性的名字空间
udf.func_doc见udf.__doc__
udf.func_name见udf.__name__
udf.func_closure包含了自由变量的引用的单元对象元祖
例,用户自定义的函数是"函数"类型
>>> def foo():pass
...
>>> type(foo)
<type 'function'>
使用type()工厂函数,我们来演示下lambda表达式返回和用户自定义函数相同的函数对象
将表达式赋值给一个别名
>>> type(foo)
<type 'function'>
>>> lambdaFunc = lambda x : x * 2
>>> lambdaFunc(100)
200
>>> type(lambdaFunc)
<type 'function'>
在一个lambda表达式上调用tpye()
>>> type(lambda:1)
<type 'function'>
查看 UDF 名字:
>>> foo.__name__
'foo'
>>> lambdaFunc.__name__
'<lambda>'
14.1.2 方法
14.3 内建方法(BIM)属性:
BIM属性描述
bim__doc__文档字串
bim.__name__字符串类型的函数名字
bim.__self__绑定的对象
内建方法(BIMs)
提供一个内建方法来访问BIM:
>>> type([].append)
<type 'builtin_function_or_method'>
通过内建函数dir()来获得他们的数据和方法属性:
>>> dir([].append)
['__call__', '__class__', '__cmp__', '__delattr__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__le__', '__lt__', '__module__', '__name__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__self__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__']
用户定义的方法(UDM)
>>> class C(object):# 定义类
... def foo(self): pass# 定义UDM
...
>>> c = C()# 实例化
>>> type(C)# 类的类别
<type 'type'>
>>> type(c)# 实例的类别
<class '__main__.C'>
>>> type(C.foo)# 非绑定方法的类别
<type 'instancemethod'>
>>> type(c.foo)# 绑定方法的类别
<type 'instancemethod'>
绑定的方法揭示了方法绑定到哪一个实例:
>>> C.foo# 非绑定方法对象
<unbound method C.foo>
>>> c.foo#绑定方法对象
<bound method C.foo of <__main__.C object at 0x7fc8d3d77790>>
>>> c# foo()实例被绑定到....
<__main__.C object at 0x7fc8d3d77790>
用户自定义属性
UDM属性描述
udm__doc__文档字符串(与udm.im_fuc.__doc__相同)
udm.__name__字符串类型的方法名字(与 umd.im_func.__name__相同)
udm.__module__定义udm模块名(或none)
udm.im_class方法相关联的类
udm.im_func方法的函数对象
udm.im_self如果绑定的话为相关联的实例,如果非绑定为none
14.1.3 类
我们可以利用类的可调用行来创建实例,实例化调用的任何参数都会传入到构造函数里
>>> class C(object):
... def __init__(self, *args):
... print 'Instantiated with these arguments:\n', args
...
>>> c1 = C()
Instantiated with these arguments:
()
>>> c2 = C('The number of the counting shall be', 3)
Instantiated with these arguments:
('The number of the counting shall be', 3)
14.1.4 类的实例:
>>> class C(object):
... def __call__(self,*args):
... print "I'm callable! Called with args:\n",args
...
>>> c = C() # 实例化
>>> c# 我们的实例
<__main__.C object at 0x7fc8d3d77950>
>>> callable(c)# 实例是可调用的
True
>>> c()# 调用实例
I'm callable! Called with args:
()
>>> c(3)# 呼叫时给一个参数
I'm callable! Called with args:
(3,)
>>> c(3,'no more,no less') # 呼叫时给两个参数
I'm callable! Called with args:
(3, 'no more,no less')
只有定义类的时候实现了__call__方法,类的实例才能成为可调用的
14.2 代码对象
可调用对象,语句,赋值,表达式,模块等这些代码块被成为代码对象
14.3 可执行的对象声明和内建函数:
内建函数和语句描述
callable(obj)如果obj可调用,返回True,否则返回FALSE
compile(string.file,type) 从type类型中创建代码对象,file是代码存放的地方
eval(obj,glo-bals=globals(),locals=locals())
对obj进行求值,obj是已编译为代码对象的表达式,或 是一个字符串表达式,可以i给出全局或者/和局部的名 字空间
exec obj执行obj,单一的python语句或者语句的集合
input(prompt='')等同于eval(raw_input(prompt="))
14.3.1 callable()
callable()是一个布尔函数,确定一个对象是否可以通过函数操作符()来调用
>>> callable(dir)#内建函数
True
>>> callable(1)#整数
False
>>> def foo(): pass
...
>>> callable(foo)#用户自定义函数
True
>>> callable('bar')#字符串
False
>>> class C(object): pass
...
>>> callable(C)#类
True
14.3.2 compile()
cmplie()函数在运行时迅速生成代码对象,然后用exec语句或者内建函数eval()来执行这些对象或者对他们进行求值
compile三个参数都必须:
1.代表要编译的Python代码
2.字符串,存放代码对象文件名,通常为空
3.字符串,有三个可能值
eval可求值的表达式[和eval()一起使用]
single单一可执行语句[和exec一起使用]
exec可执行语句组[和exec一起使用]
可求值表达式:
>>> eval_code = compile('100 + 200','','eval')
>>> eval(eval_code)
300
单一可执行语句:
>> single_code = compile('print "Hello world!"','','single')
>>> single_code
<code object <module> at 0x7fc8d3dcaf30, file "", line 1>
>>> exec single_code
Hello world!
可执行语句组:
>>> exec_code = compile("""
... req =input('Count how many numbers?')
... for eachNum in range(req):
... print eachNum
... """, '' ,'exec')
>>> exec exec_code
Count how many numbers?6
0
1
2
3
4
5
14.3.3 eval()
eval()对表达式求值,后者可以为字符串或内建函数complie()创建的预编译代码对象
>>> eval('932')
932
>>> int('932')
932
内建函数eval()接收引号内的字符串并把它作为python表达式进行求值
内建函数int()接收代表整数的字符串并把它转换成整数
当我们用纯字符串表达式,两者便不再相同:
>>> eval('100 + 200')
300
>>> int('100 + 200')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: invalid literal for int() with base 10: '100 + 200'
eval()接收一个字符串并把"100+200"作为表达式求值,当进行整数加法后给出返回值300
int()不能接收字符串等非法文字
14.3.4 exec
和eval()相似,exec语句执行代码对象或字符串形式的python代码,exec语句只接受一个参数,以下是通用语法
exec obj
例:
>>> exec """
... x = 0
... print 'x is currently:', x
... while x < 5:
... x += 1
... print 'incrementing x to:', x
... """
x is currently: 0
incrementing x to: 1
incrementing x to: 2
incrementing x to: 3
incrementing x to: 4
incrementing x to: 5
exec还可以接受有效的python文件对象,我们把上面的代码写入xcount.py文件:
# vi xcount.py
-----------------------------
#!/usr/bin/env python
exec """
x = 0
print 'x is currently:', x
while x < 5:
x += 1
print 'incrementing x to:', x
"""
-------------------------------
>>> f = open('xcount.py')
>>> exec f
x is currently: 0
incrementing x to: 1
incrementing x to: 2
incrementing x to: 3
incrementing x to: 4
incrementing x to: 5
14.3 可执行对象语句和内建函数:
一旦执行完毕,继续对exec调用就会失败,因为exec已从文件中读取了全部数据并停留在文件末尾,当用相同对象调用exec,便没有可执行代码,所以什么也不做
用tell()查看文件身在何处,然后用os.path.getsize()获取脚本大小,两个数字完全一样
>>> f.tell()# 我们文件在什么地方
125
>>> f.close()# 关闭文件
>>> from os.path import getsize
>>> getsize('xcount.py')#文件有多大
125
使用seek()可到文件最开头再次调用exec
>>> f = open('xcount.py')
>>> exec f
x is currently: 0
incrementing x to: 1
incrementing x to: 2
incrementing x to: 3
incrementing x to: 4
incrementing x to: 5
>>> exec f
>>> f.seek(0)
>>> exec f
x is currently: 0
incrementing x to: 1
incrementing x to: 2
incrementing x to: 3
incrementing x to: 4
incrementing x to: 5
14.3.5 input()
内建函数input()是eval()和raw_input()的组合,等价于eval(raw_input())
类似于raw_input(), input()有一个可选参数,该参数代表了给用户的字符串提示,不给定该字符串默认为空
raw_input()以字符串形式,逐字返回用户的输入,input()履行相同任务,还把输入作为python表达式进行求值
当用户输入一个列表时,raw_input()返回一个列表的字符串描绘,而input()返回实际列表:
>>> aString = raw_input('Enter a list: ')
Enter a list: [123,'xyz',45.67]
>>> aString
"[123,'xyz',45.67]"
>>> type(aString)
<type 'str'>
raw_input()全部返回字符串
input()把输入作为python对象来求值并返回表达式结果
>>> aList = input('Enter a list: ')
Enter a list: [123,'xyz',45.67]
>>> aList
[123, 'xyz', 45.67]
>>> type(aList)
<type 'list'>
14.3.6 使用Python在运行时生成和执行Python代码
例1,动态声称和执行Python代码:
# vi loopmake.py
-----------------------------------------------
#!/usr/bin/env python
dashes = '\n' + '-' * 50 #50个'-'号(开头换行)
#构造一个存储代码的字典(不同的键对应不同的代码),里面变量均用占位符,注意缩进
exec_dict = {
'f': """ #for loop
for %s in %s:
print %s
""",
's': """ #sequence while loop
%s = 0
%s = %s
while %s < len(%s):
print %s[%s]
%s = %s + 1
""",
'n': """ #count while loop
%s = %d
while %s < %d
print %s
%s = %s + %d
"""
}
def main():
#以下是输入用户选择的循环方式(for or while),以及操作的数据类型(数字或者序列)
ltype = raw_input('Loop type? (For/While) ')
dtype = raw_input('Data type? (Number/Seq) ')
if dtype == 'n': #表示选择数字方式
start = input('Starting value? ')
stop = input('Ending value (non-inclusive)? ')
step = input('Stepping value? ')
seq = str(range(start, stop, step)) #产生数字序列
else:
seq = raw_input('Enter sequence: ') #表示选择序列方式(需要输入序列)
var = raw_input('Iterative varible name? ') #输入用于循环的变量名称
if ltype == 'f': #如果是for循环,则按照如下方式产生代码
#这种方式没见过,给字典赋值,该复习字典了
exec_str = exec_dict['f'] % (var, seq, var) #变量依次替换占位符,直到用完
elif ltype == 'w': #如果是while循环,则需要区分是哪种数据类型:如果是序列,我们需要提供一个序列的名称(因为while循环用到了len()来求序列长度,所以名字就必须了),否则就不用了
if dtype == 's':
svar = raw_input('Enter sequence name? ')
exec_str = exec_dict['s'] % (var, svar, seq,\
var, svar, svar, var, var, var)
elif dtype == 'n':
exec_str = exec_dict['n'] % (var, start, var,\
stop, var, var, var, step)
#下面就是相应的执行和测试
print dashes
print 'Your custom-generated code: ' + dashes
print exec_str + dashes
print 'Test execution of the code:' + dashes
exec exec_str
print dashes
if __name__ == "__main__":
main()
------------------------------------
执行例子:
# python loopmake.py
Loop type? (For/While)f
Data type? (Number/Seq)n
Starting value?1
Ending value (non-inlusive)?22
Stepping value?2
Interative variable name?hehe
--------------------------------------------------
Your custom-generated code:
--------------------------------------------------
for hehe in [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21]:
print hehe
--------------------------------------------------
Test execution of the code:
--------------------------------------------------
1
3
5
7
9
11
13
15
17
19
21
--------------------------------------------------
root@ubuntu:~/python# python loopmake.py
Loop type? (For/While)f
Data type? (Number/Seq)n
Starting value?0
Ending value (non-inlusive)?4
Stepping value?1
Interative variable name?counter
--------------------------------------------------
Your custom-generated code:
--------------------------------------------------
for counter in [0, 1, 2, 3]:
print counter
--------------------------------------------------
Test execution of the code:
--------------------------------------------------
0
1
2
3
--------------------------------------------------
root@ubuntu:~/python# python loopmake.py
Loop type? (For/While)w
Data type? (Number/Seq)n
Starting value?0
Ending value (non-inlusive)?4
Stepping value?1
Interative variable name?counter
--------------------------------------------------
Your custom-generated code:
--------------------------------------------------
counter = 0
while counter < 4:
print counter
counter = counter + 1
--------------------------------------------------
Test execution of the code:
--------------------------------------------------
0
1
2
3
--------------------------------------------------
# python loopmake.py
Loop type? (For/While)f
Data type? (Number/Seq)s
Enter sequence: [932,'grail',3.0,'arrghhh']
Interative variable name?eachItem
--------------------------------------------------
Your custom-generated code:
--------------------------------------------------
for eachItem in [932,'grail',3.0,'arrghhh']:
print eachItem
--------------------------------------------------
Test execution of the code:
--------------------------------------------------
932
grail
3.0
arrghhh
--------------------------------------------------
# python loopmake.py
Loop type? (For/While)w
Data type? (Number/Seq)s
Enter sequence: [932,'grail',3.0,'arrghhh']
Interative variable name?eachIndex
Enter sequence name?myList
--------------------------------------------------
Your custom-generated code:
--------------------------------------------------
eachIndex = 0
myList = [932,'grail',3.0,'arrghhh']
while eachIndex < len(myList):
print myList[eachIndex]
eachIndex = eachIndex + 1
--------------------------------------------------
Test execution of the code:
--------------------------------------------------
932
grail
3.0
arrghhh
--------------------------------------------------
有条件的执行代码:
例14.2 调用sys.exit()使python解释器退出,exit()的任何整数参数作为退出状态会返回给调用者,该值默认为0
# vi funcAttrs.py
----------------------------------
#!/usr/bin/env python
def foo():
return True
def bar():
'bar() does not do much'
return True
foo.__doc__ = 'foo() does not do much'
foo.tester = """
if foo():
print 'PASSED'
else:
print 'FAILED'
"""
for eachAttr in dir():
obj = eval(eachAttr)
if isinstance(obj, type(foo)):
if hasattr(obj, '__doc__'):
print '\nFunction "%s" has a doc string:\n\t%s' \
%(eachAttr,obj.__doc__)
if hasattr(obj, 'tester'):
print 'Function "%s" has a tester... executing' % eachAttr
exec obj.tester
else:
print 'Function "%s" has no tester... skipping' % eachAttr
else:
print '"%s" is not a function' % eachAttr
-----------------------------------------
# python funcAttrs.py
-----------------------------------------
"__builtins__" is not a function
"__doc__" is not a function
"__file__" is not a function
"__name__" is not a function
"__package__" is not a function
Function "bar" has a doc string:
bar() does not do much
Function "bar" has no tester... skipping
Function "foo" has a doc string:
foo() does not do much
Function "foo" has a tester... executing
PASSED
-----------------------------------------
14.4 执行其他(Python)程序
14.4.1 导入
在运行时刻,有很多执行另外python脚本的方法,正如我们先前讨论的,第一次导入模块会执行模块最高级的代码,这就是python导入的行为
核心笔记:当模块导入后,就执行所有的模块
# vi import1.py
--------------------------
#!/usr/bin/env python
print 'loaded import1'
import import2
--------------------------
# vi import2.py
--------------------------
#!/usr/bin/env python
print 'loaded import2'
--------------------------
这是我们导入import1时的输出
>>> import import1
loaded import1
loaded import2
根据建议检测__name__值的迂回工作法,我们改变了import1.py和import2.py里的
这里是修改后的import.py版本:
# vi import1.py
--------------------------------
#!/usr/bin/env python
import import2
if __name__ == '__main__':
print 'loaded import1'
--------------------------------
# vi import2.py
--------------------------
#!/usr/bin/env python
if __name__ == '__main__':
print 'loaded import2'
--------------------------
当从python中导入import1时,我们避灾会得到任何输出
>>> import import1
>>>
这不意味在任何情况下都该这么编写代码,某些情况你可能想要显示输出来确定输入模块,这取决于你自身情况,我们的目的是提供实效的编程例子来屏蔽副作用
14.4.2 execfile()
通过文件对象,使用exec语句来读取python脚本的内容并执行
例:
f = open(filename,'r')
exec f
f.close
这三行可以调用execfile()来替换:
execfile(filename)
语法:
execfile(filename, globals=globals(), locals=locals())
14.4.3 将模块作为脚本执行
你可以使用命令行从你的工作目录中调用脚本
# myScript.py
或者
# python myScript.py
你想运行免费的python web服务器,以便创建和测试你自己的web页面和cgi脚本,我们可以用python -c命令行开关:
# python -c "import CGIHTTPServer; CGIHTTPServer.test()"
---------------------------------------
Serving HTTP on 0.0.0.0 port 8000 ...
---------------------------------------
我们能够在类库中执行作为脚本的模块而不是作为导入的模块,这就是-m参数的动机,现在我们可以这样运行脚本:
# python -m CGIHTTPServer
-----------------------------------------
Serving HTTP on 0.0.0.0 port 8000 ...
-----------------------------------------
14.4 执行其他(非Python)程序
在python程序里我们可以执行非python程序,包括二进制可执行文件,其他shell脚本等
14.5.1 os.system()
system()接收字符串形式的系统命令并执行
>>> import os
>>> result = os.system('cat /etc/motd')
Welcome to Ubuntu 12.10 (GNU/Linux 3.5.0-17-generic x86_64)
* Documentation: https://help.ubuntu.com/
System information as of Tue Dec 3 14:14:54 CST 2013
System load: 0.22 Processes: 76
Usage of /: 27.2% of 18.56GB Users logged in: 1
Memory usage: 24% IP address for eth0: 192.168.8.18
Swap usage: 39%
Graph this data and manage this system at https://landscape.canonical.com/
New release '13.04' available.
Run 'do-release-upgrade' to upgrade to it.
>>> result
0
>>> result = os.system('uname -a')
Linux ubuntu 3.5.0-17-generic #28-Ubuntu SMP Tue Oct 9 19:31:23 UTC 2012 x86_64 x86_64 x86_64 GNU/Linux
>>> result
0
14.5.2 os.popen()
popen()函数式文件对象和sysem()函数的结合,工作方式和system()相同,但它可以建立一个指向那个程序的单向连接,然后如访问一样访问这个程序
例,我们调用了unix程序uname来给我们提供系统相关信息,如果我们要吧字符串读入变量中并执行内部操作或把它存储到日志文件,我们可以使用popen()
>>> import os
>>> f = os.popen('uname -a')
>>> data = f.readline()
>>> print data,
Linux ubuntu 3.5.0-17-generic #28-Ubuntu SMP Tue Oct 9 19:31:23 UTC 2012 x86_64 x86_64 x86_64 GNU/Linux
popen()返回一个类文件对象;注意readlin()往往保留输入文字行尾的newline字符
14.5.3 os.fork(), os.exec*(), os.wait*()
ret = os.fork()# 产生两个进程,都返回
if ret == 0# 子进程返回的PID是0
child_suite# 子进程的代码
else:# 父进程返回时子进程的PID
parent_suite# 父进程的代码
ret = os.fork()
if ret == 0: #子进程代码
execvp('xbill', ['xbill'])
else:# 父进程代码
os.wait()
14.5.4 os.spawn*()
函数spawn*()家族和fork,exec*()相似,因为他们在新进程中执行命令
14.5.5 subprocess模块
替换os.system()
>>> from subprocess import call
>>> import os
>>> res = call(('cat','/etc/motd'))
Welcome to Ubuntu 12.10 (GNU/Linux 3.5.0-17-generic x86_64)
* Documentation: https://help.ubuntu.com/
System information as of Tue Dec 3 21:02:46 CST 2013
System load: 0.0 Processes: 76
Usage of /: 27.3% of 18.56GB Users logged in: 1
Memory usage: 25% IP address for eth0: 192.168.8.18
Swap usage: 39%
Graph this data and manage this system at https://landscape.canonical.com/
New release '13.04' available.
Run 'do-release-upgrade' to upgrade to it.
>>> res
0
取代os.popen()
创建Popen()实例的语法只比调用os.popen()函数复杂一点
>>> from subprocess import Popen,PIPE
>>> f = Popen(('uname','-a'),stdout=PIPE).stdout
>>> data = f.readline()
>>> f.close()
>>> print data,
Linux ubuntu 3.5.0-17-generic #28-Ubuntu SMP Tue Oct 9 19:31:23 UTC 2012 x86_64 x86_64 x86_64 GNU/Linux
>>> f = Popen('who', stdout=PIPE).stdout
>>> data = [ eachLine.strip() for eachLine in f]
>>> f.close
<built-in method close of file object at 0x7ff689a7a660>
>>> for eachLine in data:
... print eachLine
...
root tty1 2013-12-03 00:33
root pts/0 2013-12-03 21:02 (192.168.8.2)
14.5.6 相关函数
表14.7 各种文件执行函数:
文件对象 属性描述
os/popen2.popen2*()执行文件,打开文件,从新创建的运行程序读取(stdout),或者向该程序写(stdin)
os/popen2.popen3*()执行文件,打开文件,从新创建的运行程序读取(stdout和stder),或者向该程序写(stdin)
os/popen2.popen4*()执行文件,打开文件,从新创建的运行程序读取(stdout和stder),或者向该程序写(stdin)
commends.getoutput()在子进程中执行文件,以祖父串返回所有的输出
subprocess.call*()创建subprocess的便捷函数,Popen等待命令完成,然后返回状态代码,与os.system()类似,但是是较灵活的替代方案
14.6 受限执行
14.7 结束执行
当程序运行完成,所有模块最高级的语句执行完毕后退出,我们便称这是干净的执
行
14.7.1 sys.exit() and SystemExit
立刻退出程序并返回调用程序的主要方式是sys模块中的exit()函数
sys.exit()语法为:
system.exit(status=0)
例,调用sys.exit()使python解释器退出,exit()的任何整数参数都会以退出状态返回给调用者,该值默认为0
# vi args.py
-------------------------------
# vi args.py
#!/usr/bin/env python
import sys
def usage():
print 'At least 2 arguments(incl. cmd name).'
print 'usage: args.py arg1 arg2 [arg3...]'
sys.exit(1)
argc = len(sys.argv)
if argc < 3:
usage()
print "number of args entered:",argc
print "args (incl, cmd name) were: ", sys.argv
-------------------------------
14.7.2 sys.exitfunc()
sys.exitfunc()默认是不可用的,但是你可以改写他提供额外功能,当调用了sys.exit()并在解释器退出之前,就会用到这个函数,这个函数不带任何参数
下面例子介绍了如何设置exit()函数,如果已经被设置了,则确保执行该函数:
import sys
prev_exit_func = getattr(sys, 'exitfunc',None)
def my_exit_func(old_exit = prev_exit_func):
#:
# 进行清理
#:
if old_exit is not None and callable(old_exit):
old_exit()
sys.exitfunc = my_exit_func
对getattr()的调用可以这么写:
if hasattr(sys, 'exitfunc'):
prev_exit_func = sys.exitfunc
else:
prev_exit_func = None
14,7.3 os._exit() Function os._exit()函数
语法:
os._exit(status)
这个函数提供的功能与sys.exit()和sys.exitfunc()相反,不执行任何清理便立即退出python
14.7.4 os.kill() Fonction
os模块的kill()函数模拟传统的unix函数来发送信号SIGINT,SIGQUIT,SIGKILL给进程使进程终结
14.8 各种操作系统接口
os模块属性描述
uname()获得系统信息(主机名,操作系统版本,补丁级别,系统架构等等)
getuid()/setuid(uid)获取/设置现在进程的真正的用户ID
getpid()/getppid()获取真正的现在/父进程ID(PID)
getgid()/setgid(gid)获取/设置现在进程的群组ID
getsid()/setsid()获取会话ID(SID)或创建和返回新的SID
umask(mask)设置现在的数字unmask,同时返回先前的那个(mask用于文件许可)
getenv(ev)/
putenv(ev, value),
environ获取和设置环境变量ev的值; os.envion属性时描述当前所有环境变量的字典
......
14.9 相关模块
......