在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:
`, 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:
“,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 = `
` + `-` * 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 `
Function “%s” has a doc string:
%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 相關模組

……