1. 程式人生 > >python標準庫模組

python標準庫模組

06/07 20:10:08 編譯

def function(a, b):
print a, b

apply(function, (“whither”, “canada?”))
apply(function, (1, 2 + 3))

whither canada?
1 5

要想把關鍵字引數傳遞給一個函式, 你可以將一個字典作為 apply 函式的第 3 個引數, 參考 Example 1-2.

1.2.1.2. Example 1-2. 使用 apply 函式傳遞關鍵字引數

File: builtin-apply-example-2.py

def function(a, b):
print a, b

apply(function, (“crunchy”, “frog”))
apply(function, (“crunchy”,), {“b”: “frog”})
apply(function, (), {“a”: “crunchy”, “b”: “frog”})

crunchy frog
crunchy frog
crunchy frog

apply 函式的一個常見用法是把建構函式引數從子類傳遞到基類, 尤其是建構函式需要接受很多引數的時候. 如 Example 1-3 所示.

1.2.1.3. Example 1-3. 使用 apply 函式呼叫基類的建構函式

File: builtin-apply-example-3.py

class Rectangle:
def _ init _(self, color=“white”, width=10, height=10):
print “create a”, color, self, “sized”, width, “x”, height

class RoundedRectangle(Rectangle):
def _ init (self, **kw):
apply(Rectangle.
init _, (self,), kw)

rect = Rectangle(color=“green”, height=100, width=100)
rect = RoundedRectangle(color=“blue”, height=20)

create a green <Rectangle instance at 8c8260> sized 100 x 100
create a blue <RoundedRectangle instance at 8c84c0> sized 10 x 20

Python 2.0 提供了另個方法來做相同的事. 你只需要使用一個傳統的函式呼叫 , 使用 * 來標記元組, ** 來標記字典.

下面兩個語句是等價的:

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

1.2.2. 載入和過載模組

如果你寫過較龐大的 Python 程式, 那麼你就應該知道 import 語句是用來匯入外部模組的 (當然也可以使用 from-import 版本). 不過你可能不知道 import 其實是靠呼叫內建函式 _ _import_ _ 來工作的.

通過這個戲法你可以動態地呼叫函式. 當你只知道模組名稱(字串)的時候, 這將很方便. Example 1-4 展示了這種用法, 動態地匯入所有以 "-plugin" 結尾的模組.

1.2.2.1. Example 1-4. 使用 _ _import_ _ 函式載入模組

File: builtin-import-example-1.py

import glob, os

modules = []

for module_file in glob.glob("*-plugin.py"):
try:
module_name, ext = os.path.splitext(os.path.basename(module_file))
module = _ import _(module_name)
modules.append(module)
except ImportError:
pass # ignore broken modules

say hello to all modules

for module in modules:
module.hello()

example-plugin says hello

注意這個 plug-in 模組檔名中有個 "-" (hyphens). 這意味著你不能使用普通的 import 命令, 因為 Python 的辨識符不允許有 "-" .

1.2.2.2. Example 1-5. Plug-in 例子

File: example-plugin.py

def hello():
print “example-plugin says hello”

Example 1-6 展示瞭如何根據給定模組名和函式名獲得想要的函式物件.

1.2.2.3. Example 1-6. 使用 _ _import_ _ 函式獲得特定函式

File: builtin-import-example-2.py

def getfunctionbyname(module_name, function_name):
module = _ import _(module_name)
return getattr(module, function_name)

print repr(getfunctionbyname(“dumbdbm”, “open”))

<function open at 794fa0>

你也可以使用這個函式實現延遲化的模組匯入 (lazy module loading). 例如在 Example 1-7 中的 string 模組只在第一次使用的時候匯入.

1.2.2.4. Example 1-7. 使用 _ _import_ _ 函式實現 延遲匯入

File: builtin-import-example-3.py

class LazyImport:
def _ init _(self, module_name):
self.module_name = module_name
self.module = None
def _ getattr _(self, name):
if self.module is None:
self.module = _ import _(self.module_name)
return getattr(self.module, name)

string = LazyImport(“string”)

print string.lowercase

abcdefghijklmnopqrstuvwxyz

Python 也提供了重新載入已載入模組的基本支援. [Example 1-8 #eg-1-8 會載入 3 次 hello.py 檔案.

1.2.2.5. Example 1-8. 使用 reload 函式

File: builtin-reload-example-1.py

import hello
reload(hello)
reload(hello)

hello again, and welcome to the show
hello again, and welcome to the show
hello again, and welcome to the show

reload 直接接受模組作為引數.

[!Feather 注:  ^ 原句無法理解, 稍後討論.]

注意,當你重載入模組時, 它會被重新編譯, 新的模組會代替模組字典裡的老模組. 但是, 已經用原模組裡的類建立的例項仍然使用的是老模組(不會被更新).

同樣地, 使用 from-import 直接建立的到模組內容的引用也是不會被更新的.

1.2.3. 關於名稱空間

dir 返回由給定模組, 類, 例項, 或其他型別的所有成員組成的列表. 這可能在互動式 Python 直譯器下很有用, 也可以用在其他地方.Example 1-9展示了 dir 函式的用法.

1.2.3.1. Example 1-9. 使用 dir 函式

File: builtin-dir-example-1.py

def dump(value):
print value, “=>”, dir(value)

import sys

dump(0)
dump(1.0)
dump(0.0j) # complex number
dump([]) # list
dump({}) # dictionary
dump(“string”)
dump(len) # function
dump(sys) # module

0 => []
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 => []
<built-in function len> => [’_ doc ', ’ name ', ’ self ‘]
<module ‘sys’ (built-in)> => [’
doc ', ’ name ',
stderr ', ’ stdin ', ’ stdout _’, ‘argv’,
‘builtin_module_names’, ‘copyright’, ‘dllhandle’,
‘exc_info’, ‘exc_type’, ‘exec_prefix’, ‘executable’,

在例子 Example 1-10中定義的 getmember 函式返回給定類定義的所有類級別的屬性和方法.

1.2.3.2. Example 1-10. 使用 dir 函式查詢類的所有成員

File: builtin-dir-example-2.py

class A:
def a(self):
pass
def b(self):
pass

class B(A):
def c(self):
pass
def d(self):
pass

def getmembers(klass, members=None):
# get a list of all class members, ordered by class
if members is None:
members = []
for k in klass._ bases _:
getmembers(k, members)
for m in dir(klass):
if m not in members:
members.append(m)
return members

print getmembers(A)
print getmembers(B)
print getmembers(IOError)

[’_ doc ', ’ module ‘, ‘a’, ‘b’]
[’
doc ', ’ module ‘, ‘a’, ‘b’, ‘c’, ‘d’]
[’
doc ', ’ getitem ', ’ init ', ’ module ', ’ str _’]

getmembers 函式返回了一個有序列表. 成員在列表中名稱出現的越早, 它所處的類層次就越高. 如果無所謂順序的話, 你可以使用字典代替列表.

[!Feather 注: 字典是無序的, 而列表和元組是有序的, 網上有關於有序字典的討論]

vars 函式與此相似, 它返回的是包含每個成員當前值的字典. 如果你使用不帶引數的 vars , 它將返回當前區域性名稱空間的可見元素(同locals() 函式 ). 如 Example 1-11所表示.

1.2.3.3. Example 1-11. 使用 vars 函式

File: builtin-vars-example-1.py

book = “library2”
pages = 250
scripts = 350

print “the %(book)s book contains more than %(scripts)s scripts” % vars()

the library book contains more than 350 scripts

1.2.4. 檢查物件型別

Python 是一種動態型別語言, 這意味著給一個定變數名可以在不同的場合繫結到不同的型別上. 在接下面例子中, 同樣的函式分別被整數, 浮點數, 以及一個字串呼叫:

def function(value):
    print value
function(1)
function(1.0)
function("one")

type 函式 (如 Example 1-12 所示) 允許你檢查一個變數的型別. 這個函式會返回一個type descriptor (型別描述符), 它對於 Python 直譯器提供的每個型別都是不同的.

1.2.4.1. Example 1-12. 使用 type 函式

File: builtin-type-example-1.py

def dump(value):
print type(value), value

dump(1)
dump(1.0)
dump(“one”)

<type ‘int’> 1
<type ‘float’> 1.0
<type ‘string’> one

每個型別都有一個對應的型別物件, 所以你可以使用 is 操作符 (物件身份?) 來檢查型別. (如 Example 1-13所示).

1.2.4.2. Example 1-13. 對檔名和檔案物件使用 type 函式

File: builtin-type-example-2.py

def load(file):
if isinstance(file, type("")):
file = open(file, “rb”)
return file.read()

print len(load(“samples/sample.jpg”)), “bytes”
print len(load(open(“samples/sample.jpg”, “rb”))), “bytes”

4672 bytes
4672 bytes

callable 函式, 如 Example 1-14 所示, 可以檢查一個物件是否是可呼叫的 (無論是直接呼叫或是通過apply). 對於函式, 方法, lambda 函式, 類, 以及實現了 _ _call_ _ 方法的類例項, 它都返回 True.

1.2.4.3. Example 1-14. 使用 callable 函式

File: builtin-callable-example-1.py

def dump(function):
if callable(function):
print function, “is callable”
else:
print function, “is not callable”

class A:
def method(self, value):
return value

class B(A):
def _ call _(self, value):
return value

a = A()
b = B()

dump(0) # simple objects
dump(“string”)
dump(callable)
dump(dump) # function

dump(A) # classes
dump(B)
dump(B.method)

dump(a) # instances
dump(b)
dump(b.method)

0 is not callable
string is not callable
<built-in function callable> is callable
<function dump at 8ca320> is callable
A is callable
B is callable
<unbound method A.method> is callable
<A instance at 8caa10> is not callable
<B instance at 8cab00> is callable
<method A.method of B instance at 8cab00> is callable

注意類物件 (A 和 B) 都是可呼叫的; 如果呼叫它們, 就產生新的物件(類例項). 但是 A 類的例項不可呼叫, 因為它的類沒有實現 _ _call_ _ 方法.

你可以在 operator 模組中找到檢查物件是否為某一內建型別(數字, 序列, 或者字典等)的函式. 但是, 因為建立一個類很簡單(比如實現基本序列方法的類), 所以對這些型別使用顯式的型別判斷並不是好主意.

在處理類和例項的時候會複雜些. Python 不會把類作為本質上的型別對待; 相反地, 所有的類都屬於一個特殊的類型別(special class type), 所有的類例項屬於一個特殊的例項型別(special instance type).

這意味著你不能使用 type 函式來測試一個例項是否屬於一個給定的類; 所有的例項都是同樣的型別! 為了解決這個問題, 你可以使用isinstance 函式,它會檢查一個物件是不是給定類(或其子類)的例項. Example 1-15 展示了 isinstance 函式的使用.

1.2.4.4. Example 1-15. 使用 isinstance 函式

File: builtin-isinstance-example-1.py

class A:
pass

class B:
pass

class C(A):
pass

class D(A, B):
pass

def dump(object):
print object, “=>”,
if isinstance(object, A):
print “A”,
if isinstance(object, B):
print “B”,
if isinstance(object, C):
print “C”,
if isinstance(object, D):
print “D”,
print

a = A()
b = B()
c = C()
d = D()

dump(a)
dump(b)
dump©
dump(d)
dump(0)
dump(“string”)

<A instance at 8ca6d0> => A
<B instance at 8ca750> => B
<C instance at 8ca780> => A C
<D instance at 8ca7b0> => A B D
0 =>
string =>

issubclass 函式與此相似, 它用於檢查一個類物件是否與給定類相同, 或者是給定類的子類. 如 Example 1-16 所示.

注意, isinstance 可以接受任何物件作為引數, 而 issubclass 函式在接受非類物件引數時會引發TypeError 異常.

1.2.4.5. Example 1-16. 使用 issubclass 函式

File: builtin-issubclass-example-1.py

class A:
pass

class B:
pass

class C(A):
pass

class D(A, B):
pass

def dump(object):
print object, “=>”,
if issubclass(object, A):
print “A”,
if issubclass(object, B):
print “B”,
if issubclass(object, C):
print “C”,
if issubclass(object, D):
print “D”,
print

dump(A)
dump(B)
dump©
dump(D)
dump(0)
dump(“string”)

A => A
B => B
C => A C
D => A B D
0 =>
Traceback (innermost last):
File “builtin-issubclass-example-1.py”, line 29, in ?
File “builtin-issubclass-example-1.py”, line 15, in dump
TypeError: arguments must be classes

1.2.5. 計算 Python 表示式

Python 提供了在程式中與直譯器互動的多種方法. 例如 eval 函式將一個字串作為 Python 表示式求值. 你可以傳遞一串文字, 簡單的表示式, 或者使用內建 Python 函式. 如Example 1-17 所示.

1.2.5.1. Example 1-17. 使用 eval 函式

File: builtin-eval-example-1.py

def dump(expression):
result = eval(expression)
print expression, “=>”, result, type(result)

dump(“1”)
dump(“1.0”)
dump("‘string’")
dump(“1.0 + 2.0”)
dump("’*’ * 10")
dump(“len(‘world’)”)

1 => 1 <type ‘int’>
1.0 => 1.0 <type ‘float’>
‘string’ => string <type ‘string’>
1.0 + 2.0 => 3.0 <type ‘float’>
‘*’ * 10 => ********** <type ‘string’>
len(‘world’) => 5 <type ‘int’>

如果你不確定字串來源的安全性, 那麼你在使用 eval 的時候會遇到些麻煩. 例如, 某個使用者可能會使用 _ _import_ _ 函式載入os 模組, 然後從硬碟刪除檔案 (如 Example 1-18 所示).

1.2.5.2. Example 1-18. 使用 eval 函式執行任意命令

File: builtin-eval-example-2.py

print eval("_ import (‘os’).getcwd()")
print eval("
import _(‘os’).remove(‘file’)")

/home/fredrik/librarybook
Traceback (innermost last):
File “builtin-eval-example-2”, line 2, in ?
File “<string>”, line 0, in ?
os.error: (2, ‘No such file or directory’)

這裡我們得到了一個 os.error 異常, 這說明 Python 事實上在嘗試刪除檔案!

幸運地是, 這個問題很容易解決. 你可以給 eval 函式傳遞第 2 個引數, 一個定義了該表示式求值時名稱空間的字典. 我們測試下, 給函式傳遞個空字典:

>>> print eval("_ _import_ _('os').remove('file')", {})
Traceback (innermost last):
  File "<stdin>", line 1, in ?
  File "<string>", line 0, in ?
os.error: (2, 'No such file or directory')

呃.... 我們還是得到了個 os.error 異常.

這是因為 Python 在求值前會檢查這個字典, 如果沒有發現名稱為 _ _builtins_ _ 的變數(複數形式), 它就會新增一個:

>>> namespace = {}
>>> print eval("_ _import_ _('os').remove('file')", namespace)
Traceback (innermost last):
  File "<stdin>", line 1, in ?
  File "<string>", line 0, in ?
os.error: (2, 'No such file or directory')
>>> namespace.keys()
['_ _builtins_ _']

如果你列印這個 namespace 的內容, 你會發現裡邊有所有的內建函式.

[!Feather 注: 如果我RP不錯的話, 新增的這個_ _builtins_ _就是當前的_ _builtins_ _]

我們注意到瞭如果這個變數存在, Python 就不會去新增預設的, 那麼我們的解決方法也來了, 為傳遞的字典引數加入一個 _ _builtins_ _ 項即可. 如Example 1-19 所示.

1.2.5.3. Example 1-19. 安全地使用 eval 函式求值

File: builtin-eval-example-3.py

print eval("_ import (‘os’).getcwd()", {})
print eval("
import (‘os’).remove(‘file’)", {" builtins _": {}})

/home/fredrik/librarybook
Traceback (innermost last):
File “builtin-eval-example-3.py”, line 2, in ?
File “<string>”, line 0, in ?
NameError: _ import _

即使這樣, 你仍然無法避免針對 CPU 和記憶體資源的攻擊. (比如, 形如 eval("'*'*1000000*2*2*2*2*2*2*2*2*2") 的語句在執行後會使你的程式耗盡系統資源).

1.2.6. 編譯和執行程式碼

eval 函式只針對簡單的表示式. 如果要處理大塊的程式碼, 你應該使用 compile exec 函式 (如 Example 1-20 所示).

1.2.6.1. Example 1-20. 使用 compile 函式檢查語法

File: builtin-compile-example-1.py

BODY = “”"
prnt ‘owl-stretching time’
“”"

try:
compile(BODY, NAME, “exec”)
except SyntaxError, v:
print “syntax error:”, v, “in”, NAME

syntax error: invalid syntax in script.py

成功執行後, compile 函式會返回一個程式碼物件, 你可以使用 exec 語句執行它, 參見 Example 1-21 .

1.2.6.2. Example 1-21. 執行已編譯的程式碼

File: builtin-compile-example-2.py

BODY = “”"
print ‘the ant, an introduction’
“”"

code = compile(BODY, “<script>”, “exec”)

print code

exec code

<code object ? at 8c6be0, file “<script>”, line 0>
the ant, an introduction

使用 Example 1-22 中的類可以在程式執行時實時地生成程式碼. write 方法用於新增程式碼, indentdedent 方法用於控制縮排結構. 其他部分交給類來處理.

1.2.6.3. Example 1-22. 簡單的程式碼生成工具

File: builtin-compile-example-3.py

import sys, string

class CodeGeneratorBackend:
“Simple code generator for Python”

def begin(self, tab="/t"):
    self.code = []
    self.tab = tab
    self.level = 0

def end(self):
    self.code.append("") # make sure there's a newline at the end 
    return compile(string.join(self.code, "/n"), "&lt;code&gt;", "exec")

def write(self, string):
    self.code.append(self.tab * self.level + string)

def indent(self):
    self.level = self.level + 1
    # in 2.0 and later, this can be written as: self.level += 1

def dedent(self):
    if self.level == 0:
        raise SyntaxError, "internal error in code generator"
    self.level = self.level - 1
    # or: self.level -= 1

try it out!

c = CodeGeneratorBackend()
c.begin()
c.write(“for i in range(5):”)
c.indent()
c.write(“print ‘code generation made easy!’”)
c.dedent()
exec c.end()

code generation made easy!
code generation made easy!
code generation made easy!
code generation made easy!
code generation made easy!

Python 還提供了 execfile 函式, 一個從檔案載入程式碼, 編譯程式碼, 執行程式碼的快捷方式. Example 1-23 簡單地展示瞭如何使用這個函式.

1.2.6.4. Example 1-23. 使用 execfile 函式

File: builtin-execfile-example-1.py

execfile(“hello.py”)

def EXECFILE(filename, locals=None, globals=None):
exec compile(open(filename).read(), filename, “exec”) in locals, globals

EXECFILE(“hello.py”)

hello again, and welcome to the show
hello again, and welcome to the show

1.2.6.5. Example 1-24. hello.py 指令碼

File: hello.py

print “hello again, and welcome to the show”

1.2.7. 從 _ _builtin_ _ 模組過載函式

因為 Python 在檢查區域性名稱空間和模組名稱空間前不會檢查內建函式, 所以有時候你可能要顯式地引用 _ _builtin_ _ 模組. 例如Example 1-25 過載了內建的 open 函式. 這時候要想使用原來的open 函式, 就需要指令碼顯式地指明模組名稱.

1.2.7.1. Example 1-25. 顯式地訪問 _ _builtin_ _ 模組中的函式

File: builtin-open-example-1.py

def open(filename, mode=“rb”):
import _ builtin _
file = _ builtin _.open(filename, mode)
if file.read(5) not in(“GIF87”, “GIF89”):
raise IOError, “not a GIF file”
file.seek(0)
return file

fp = open(“samples/sample.gif”)
print len(fp.read()), “bytes”

fp = open(“samples/sample.jpg”)
print len(fp.read()), “bytes”

3565 bytes
Traceback (innermost last):
File “builtin-open-example-1.py”, line 12, in ?
File “builtin-open-example-1.py”, line 5, in open
IOError: not a GIF file

[!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: NULL globals" ). 這本書的作者編了 5 年程式都沒見過這個錯誤. (想必是沒有用raise SystemError).
  • MemoryError(StandardError) , 當直譯器耗盡記憶體時會引發該異常. 注意只有在底層記憶體分配抱怨時這個異常才會發生; 如果是在你的舊機器上, 這個異常發生之前系統會陷入混亂的記憶體交換中.

你可以建立自己的異常類. 只需要繼承內建的 Exception 類(或者它的任意一個合適的子類)即可, 有需要時可以再過載它的 _ _str_ _ 方法. Example 1-26 展示瞭如何使用 exceptions 模組.

1.3.0.1. Example 1-26. 使用 exceptions 模組

File: exceptions-example-1.py

python imports this module by itself, so the following

line isn’t really needed

python 會自動匯入該模組, 所以以下這行是不必要的

import exceptions

class HTTPError(Exception):
# indicates an HTTP protocol error
def _ init _(self, url, errcode, errmsg):
self.url = url
self.errcode = errcode
self.errmsg = errmsg
def _ str _(self):
return (
“<HTTPError for %s: %s %s>” %
(self.url, self.errcode, self.errmsg)
)

try:
raise HTTPError(“http://www.python.org/foo”, 200, “Not Found”)
except HTTPError, error:
print “url”, “=>”, error.url
print “errcode”, “=>”, error.errcode
print “errmsg”, “=>”, error.errmsg
raise # reraise exception

url => http://www.python.org/foo
errcode => 200
errmsg => Not Found
Traceback (innermost last):
File “exceptions-example-1”, line 16, in ?
HTTPError: <HTTPError for http://www.python.org/foo: 200 Not Found>

1.4. os 模組

這個模組中的大部分函式通過對應平臺相關模組實現, 比如 posixnt. os 模組會在第一次匯入的時候自動載入合適的執行模組.

1.4.1. 處理檔案

內建的 open / file 函式用於建立, 開啟和編輯檔案, 如 Example 1-27 所示. 而 os 模組提供了重新命名和刪除檔案所需的函式.

1.4.1.1. Example 1-27. 使用 os 模組重新命名和刪除檔案

File: os-example-3.py

import os
import string

def replace(file, search_for, replace_with):
# replace strings in a text file

back = os.path.splitext(file)[0] + ".bak"
temp = os.path.splitext(file)[0] + ".tmp"

try:
    # remove old temp file, if any
    os.remove(temp)
except os.error:
    pass

fi = open(file)
fo = open(temp, "w")

for s in fi.readlines():
    fo.write(string.replace(s, search_for, replace_with))

fi.close()
fo.close()

try:
    # remove old backup file, if any
    os.remove(back)
except os.error:
    pass

# rename original to backup...
os.rename(file, back)

# ...and temporary to original
os.rename(temp, file)

try it out!

file = “samples/sample.txt”

replace(file, “hello”, “tjena”)
replace(file, “tjena”, “hello”)

1.4.2. 處理目錄

os 模組也包含了一些用於目錄處理的函式.

listdir 函式返回給定目錄中所有檔名(包括目錄名)組成的列表, 如 Example 1-28 所示. 而 Unix 和 Windows 中使用的當前目錄和父目錄標記(. 和 .. )不包含在此列表中.

1.4.2.1. Example 1-28. 使用 os 列出目錄下的檔案

File: os-example-5.py

import os

for file in os.listdir(“samples”):
print file

sample.au
sample.jpg
sample.wav

getcwdchdir 函式分別用於獲得和改變當前工作目錄. 如 Example 1-29 所示.

1.4.2.2. Example 1-29. 使用 os 模組改變當前工作目錄

File: os-example-4.py

import os

where are we?

cwd = os.getcwd()
print “1”, cwd

go down

os.chdir(“samples”)
print “2”, os.getcwd()

go back up

os.chdir(os.pardir)
print “3”, os.getcwd()

1 /ematter/librarybook
2 /ematter/librarybook/samples
3 /ematter/librarybook

makedirsremovedirs 函式用於建立或刪除目錄層,如 Example 1-30 所示.

1.4.2.3. Example 1-30. 使用 os 模組建立/刪除多個目錄級

File: os-example-6.py

import os

os.makedirs(“test/multiple/levels”)

fp = open(“test/multiple/levels/file”, “w”)
fp.write(“inspector praline”)
fp.close()

remove the file

os.remove(“test/multiple/levels/file”)

and all empty directories above it

os.removedirs(“test/multiple/levels”)

removedirs 函式會刪除所給路徑中最後一個目錄下所有的空目錄. 而 mkdir rmdir 函式只能處理單個目錄級. 如 Example 1-31 所示.

1.4.2.4. Example 1-31. 使用 os 模組建立/刪除目錄

File: os-example-7.py

import os

os.mkdir(“test”)
os.rmdir(“test”)

os.rmdir(“samples”) # this will fail

Traceback (innermost last):
File “os-example-7”, line 6, in ?
OSError: [Errno 41] Directory not empty: ‘samples’

如果需要刪除非空目錄, 你可以使用 shutil 模組中的 rmtree 函式.

1.4.3. 處理檔案屬性

stat 函式可以用來獲取一個存在檔案的資訊, 如 Example 1-32 所示. 它返回一個類元組物件(stat_result物件, 包含 10 個元素), 依次是st_mode (許可權模式), st_ino (inode number), st_dev (device), st_nlink (number of hard links), st_uid (所有者使用者 ID), st_gid (所有者所在組 ID ), st_size (檔案大小, 位元組), st_atime (最近一次訪問時間), st_mtime (最近修改時間), st_ctime (平臺相關; Unix下的最近一次元資料/metadata修改時間, 或者 Windows 下的建立時間) - 以上專案也可作為屬性訪問.

[!Feather 注: 原文為 9 元元組. 另,返回物件並非元組型別,為 struct.]

1.4.3.1. Example 1-32. 使用 os 模組獲取檔案屬性

File: os-example-1.py

import os
import time

file = “samples/sample.jpg”

def dump(st):
mode, ino, dev, nlink, uid, gid, size, atime, mtime, ctime = st
print “- size:”, size, “bytes”
print “- owner:”, uid, gid
print “- created:”, time.ctime(ctime)
print “- last accessed:”, time.ctime(atime)
print “- last modified:”, time.ctime(mtime)
print “- mode:”, oct(mode)
print “- inode/dev:”, ino, dev

get stats for a filename

st = os.stat(file)

print “stat”, file
dump(st)
print

get stats for an open file

fp = open(file)

st = os.fstat(fp.fileno())

print “fstat”, file
dump(st)

stat samples/sample.jpg

  • size: 4762 bytes
  • owner: 0 0
  • created: Tue Sep 07 22:45:58 1999
  • last accessed: Sun Sep 19 00:00:00 1999
  • last modified: Sun May 19 01:42:16 1996
  • mode: 0100666
  • inode/dev: 0 2

fstat samples/sample.jpg

  • size: 4762 bytes
  • owner: 0 0
  • created: Tue Sep 07 22:45:58 1999
  • last accessed: Sun Sep 19 00:00:00 1999
  • last modified: Sun May 19 01:42:16 1996
  • mode: 0100666
  • inode/dev: 0 0

返回物件中有些屬性在非 Unix 平臺下是無意義的, 比如 (st_inode , st_dev)為 Unix 下的為每個檔案提供了唯一標識, 但在其他平臺可能為任意無意義資料 .

stat 模組包含了很多可以處理該返回物件的常量及函式. 下面的程式碼展示了其中的一些.

可以使用 chmodutime 函式修改檔案的許可權模式和時間屬性,如 Example 1-33 所示.

1.4.3.2. Example 1-33. 使用 os 模組修改檔案的許可權和時間戳

File: os-example-2.py

import os
import stat, time

infile = “samples/sample.jpg”
outfile = “out.jpg”

copy contents

fi = open(infile, “rb”)
fo = open(outfile, “wb”)

while 1:
s = fi.read(10000)
if not s:
break
fo.write(s)

fi.close()
fo.close()

copy mode and timestamp

st = 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 =>
mode 0666
atime Thu Oct 14 15:15:50 1999
mtime Mon Nov 13 15:42:36 1995
copy =>
mode 0666
atime Thu Oct 14 15:15:50 1999
mtime Mon Nov 13 15:42:36 1995

1.4.4. 處理程序

system 函式在當前程序下執行一個新命令, 並等待它完成, 如 Example 1-34 所示.

1.4.4.1. Example 1-34. 使用 os 執行作業系統命令

File: os-example-8.py

import os

if os.name == “nt”:
command = “dir”
else:
command = “ls -l”

os.system(command)

-rwxrw-r-- 1 effbot effbot 76 Oct 9 14:17 README
-rwxrw-r-- 1 effbot effbot 1727 Oct 7 19:00 SimpleAsyncHTTP.py
-rwxrw-r-- 1 effbot effbot 314 Oct 7 20:29 aifc-example-1.py
-rwxrw-r-- 1 effbot effbot 259 Oct 7 20:38 anydbm-example-1.py

命令通過作業系統的標準 shell 執行, 並返回 shell 的退出狀態. 需要注意的是在 Windows 95/98 下, shell 通常是 command.com , 它的推出狀態總是 0.

由於 11os.system11 直接將命令傳遞給 shell , 所以如果你不檢查傳入引數的時候會很危險 (比如命令 os.system("viewer %s" % file), 將 file 變數設定為 "sample.jpg; rm -rf $HOME" ....). 如果不確定引數的安全性, 那麼最好使用execspawn 代替(稍後介紹).

exec 函式會使用新程序替換當前程序(或者說是"轉到程序"). 在 Example 1-35 中, 字串 "goodbye" 永遠不會被列印.

1.4.4.2. Example 1-35. 使用 os 模組啟動新程序

File: os-exec-example-1.py

import os
import sys

program = “python”
arguments = [“hello.py”]

print os.execvp(program, (program,) + tuple(arguments))
print “goodbye”

hello again, and welcome to the show

Python 提供了很多表現不同的 exec 函式. Example 1-35 使用的是execvp 函式, 它會從標準路徑搜尋執行程式, 把第二個引數(元組)作為單獨的引數傳遞給程式, 並使用當前的環境變數來執行程式. 其他七個同類型函式請參閱Python Library Reference .

在 Unix 環境下, 你可以通過組合使用 exec , fork 以及 wait 函式來從當前程式呼叫另一個程式, 如Example 1-36 所示. fork 函式複製當前程序,wait 函式會等待一個子程序執行結束.

1.4.4.3. Example 1-36. 使用 os 模組呼叫其他程式 (Unix)

File: os-exec-example-2.py

import os
import sys

def run(program, *args):
pid = os.fork()
if not pid:
os.execvp(program, (program,) + args)
return os.wait()[0]

run(“python”, “hello.py”)

print “goodbye”

hello again, and welcome to the show
goodbye

fork 函式在子程序返回中返回 0 (這個程序首先從 fork 返回值), 在父程序中返回一個非 0 的程序識別符號(子程序的 PID ). 也就是說, 只有當我們處於子程序的時候 "not pid" 才為真.

forkwait 函式在 Windows 上是不可用的, 但是你可以使用 spawn 函式, 如Example 1-37 所示. 不過, spawn 不會沿著路徑搜尋可執行檔案, 你必須自己處理好這些.

1.4.4.4. Example 1-37. 使用 os 模組呼叫其他程式 (Windows)

File: os-spawn-example-1.py

import os
import string

def run(program, *args):
# find executable
for path in string.split(os.environ[“PATH”], os.pathsep):
file = os.path.join(path, program) + “.exe”
try:
return os.spawnv(os.P_WAIT, file, (file,) + args)
except os.error:
pass
raise os.error, “cannot find executable”

run(“python”, “hello.py”)

print “goodbye”

hello again, and welcome to the show
goodbye

spawn 函式還可用於在後臺執行一個程式. Example 1-38run 函式添加了一個可選的 mode 引數; 當設定為 os.P_NOWAIT 時, 這個指令碼不會等待子程式結束, 預設值os.P_WAITspawn 會等待子程序結束.

其它的標誌常量還有 os.P_OVERLAY ,它使得 spawn 的行為和 exec 類似, 以及os.P_DETACH , 它在後臺執行子程序, 與當前控制檯和鍵盤焦點隔離.

1.4.4.5. Example 1-38. 使用 os 模組在後臺執行程式 (Windows)

File: os-spawn-example-2.py

import os
import string

def run(program, *args, **kw):
# find executable
mode = kw.get(“mode”, os.P_WAIT)
for path in string.split(os.environ[“PATH”], os.pathsep):
file = os.path.join(path, program) + “.exe”
try:
return os.spawnv(mode, file, (file,) + args)
except os.error:
pass
raise os.error, “cannot find executable”

run(“python”, “hello.py”, mode=os.P_NOWAIT)
print “goodbye”

goodbye
hello again, and welcome to the show

Example 1-39 提供了一個在 Unix 和 Windows 平臺上通用的spawn 方法.

1.4.4.6. Example 1-39. 使用 spawn 或 fork/exec 呼叫其他程式

File: os-spawn-example-3.py

import os
import string

if os.name in (“nt”, “dos”):
exefile = “.exe”
else:
exefile = “”

def spawn(program, *args):
try:
# possible 2.0 shortcut!
return os.spawnvp(program, (program,) + args)
except AttributeError:
pass
try:
spawnv = os.spawnv
except AttributeError:

    # assume it's unix
    pid = os.fork()
    if not pid:
        os.execvp(program, (program,) + args)
    return os.wait()[0]
else:
    # got spawnv but no spawnp: go look for an executable
    for path in string.split(os.environ["PATH"], os.pathsep):
        file = os.path.join(path, program) + exefile
        try:
            return spawnv(os.P_WAIT, file, (file,) + args)
        except os.error:
            pass
    raise IOError, "cannot find executable"

try it out!

spawn(“python”, “hello.py”)

print “goodbye”

hello again, and welcome to the show
goodbye

Example 1-39 首先嚐試呼叫 spawnvp 函式. 如果該函式不存在(一些版本/平臺沒有這個函式), 它將繼續查詢一個名為spawnv 的函式並且開始查詢程式路徑. 作為最後的選擇, 它會呼叫 execfork 函式完成工作.

1.4.5. 處理守護程序(Daemon Processes)

Unix 系統中, 你可以使用 fork 函式把當前程序轉入後臺(一個"守護者/daemon"). 一般來說, 你需要派生(fork off)一個當前程序的副本, 然後終止原程序, 如Example 1-40 所示.

1.4.5.1. Example 1-40. 使用 os 模組使指令碼作為守護執行 (Unix)

File: os-example-14.py

import os
import time

pid = os.fork()
if pid:
os._exit(0) # kill original

print “daemon started”
time.sleep(10)
print “daemon terminated”

需要建立一個真正的後臺程式稍微有點複雜, 首先呼叫 setpgrp 函式建立一個 "程序組首領/process group leader". 否則, 向無關程序組傳送的訊號(同時)會引起守護程序的問題:

os.setpgrp()

為了確保守護程序建立的檔案能夠獲得程式指定的 mode flags(許可權模式標記?), 最好刪除 user mode mask:

os.umask(0)

然後, 你應該重定向 stdout/stderr 檔案, 而不能只是簡單地關閉它們(如果你的程式需要 stdoutstderr 寫入內容的時候, 可能會出現意想不到的問題).

class NullDevice:
    def write(self, s):
        pass
sys.stdin.close()
sys.stdout = NullDevice()
sys.stderr = NullDevice()

換言之, 由於 Python 的 print 和 C 中的 printf/fprintf 在裝置(device)沒有連線後不會關閉你的程式, 此時守護程序中的sys.stdout.write() 會丟擲一個 IOError 異常, 而你的程式依然在後臺執行的很好....

另外, 先前例子中的 _exit 函式會終止當前程序. 而 sys.exit 不同, 如果呼叫者(caller)捕獲了SystemExit 異常, 程式仍然會繼續執行. 如 Example 1-41 所示.

1.4.5.2. Example 1-41. 使用 os 模組終止當前程序

File: os-example-9.py

import os
import sys

try:
sys.exit(1)
except SystemExit, value:
print “caught exit(%s)” % value

try:
os._exit(2)
except SystemExit, value:
print “caught exit(%s)” % value

print “bye!”

caught exit(1)

1.5. os.path 模組

os.path 模組包含了各種處理長檔名(路徑名)的函式. 先匯入 (import) os 模組, 然後就可以以os.path 訪問該模組.

1.5.1. 處理檔名

os.path 模組包含了許多與平臺無關的處理長檔名的函式. 也就是說, 你不需要處理前後斜槓, 冒號等. 我們可以看看 Example 1-42 中的樣例程式碼.

1.5.1.1. Example 1-42. 使用 os.path 模組處理檔名

File: os-path-example-1.py

import os

filename = “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))

using nt …
split => (‘my/little’, ‘pony’)
splitext => (‘my/little/pony’, ‘’)
dirname => my/little
basename => pony
join => my/little/pony

注意這裡的 split 只分割出最後一項(不帶斜槓).

os.path 模組中還有許多函式允許你簡單快速地獲知檔名的一些特徵,如 Example 1-43 所示。

1.5.1.2. Example 1-43. 使用 os.path 模組檢查檔名的特徵

File: os-path-example-2.py

import os

FILES = (
os.curdir,
“/”,
“file”,
“/file”,
“samples”,
“samples/sample.jpg”,
“directory/file”,
“…/directory/file”,
“/directory/file”
)

for file in FILES:
print file, “=>”,
if os.path.exists(file):
print “EXISTS”,
if os.path.isabs(file):
print “ISABS”,
if os.path.isdir(file):
print “ISDIR”,
if os.path.isfile(file):
print “ISFILE”,
if os.path.islink(file):
print “ISLINK”,
if os.path.ismount(file):
print “ISMOUNT”,
print

. => EXISTS ISDIR
/ => EXISTS ISABS ISDIR ISMOUNT
file =>
/file => ISABS
samples => EXISTS ISDIR
samples/sample.jpg => EXISTS ISFILE
directory/file =>
…/directory/file =>
/directory/file => ISABS

expanduser 函式以與大部分Unix shell相同的方式處理使用者名稱快捷符號(~, 不過在 Windows 下工作不正常), 如Example 1-44 所示.

1.5.1.3. Example 1-44. 使用 os.path 模組將使用者名稱插入到檔名

File: os-path-expanduser-example-1.py

import os

print os.path.expanduser("~/.pythonrc")

/home/effbot/.pythonrc

expandvars 函式將檔名中的環境變數替換為對應值, 如 Example 1-45 所示.

1.5.1.4. Example 1-45. 使用 os.path 替換檔名中的環境變數

File: os-path-expandvars-example-1.py

import os

os.environ[“USER”] = “user”

print os.path.expandvars("/home/USER/config&quot;)printos.path.expandvars(&quot;USER/config&quot;) print os.path.expandvars(&quot;USER/folders")

/home/user/config
user/folders

1.5.2. 搜尋檔案系統

walk 函式會幫你找出一個目錄樹下的所有檔案 (如 Example 1-46 所示). 它的引數依次是目錄名, 回撥函式, 以及傳遞給回撥函式的資料物件.

1.5.2.1. Example 1-46. 使用 os.path 搜尋檔案系統

File: os-path-walk-example-1.py

import os

def callback(arg, directory, files):
for file in files:
print os.path.join(directory, file), repr(arg)

os.path.walk(".", callback, “secret message”)

./aifc-example-1.py ‘secret message’
./anydbm-example-1.py ‘secret message’
./array-example-1.py ‘secret message’

./samples ‘secret message’
./samples/sample.jpg ‘secret message’
./samples/sample.txt ‘secret message’
./samples/sample.zip ‘secret message’
./samples/articles ‘secret message’
./samples/articles/article-1.txt ‘secret message’
./samples/articles/article-2.txt ‘secret message’

walk 函式的介面多少有點晦澀 (也許只是對我個人而言, 我總是記不住引數的順序). Example 1-47 中展示的 index 函式會返回一個檔名列表, 你可以直接使用 for-in 迴圈處理檔案.

1.5.2.2. Example 1-47. 使用 os.listdir 搜尋檔案系統

File: os-path-walk-example-2.py

import os

def index(directory):
# like os.listdir, but traverses directory trees
stack = [directory]
files = []
while stack:
directory = stack.pop()
for file in os.listdir(directory):
fullname = os.path.join(directory, file)
files.append(fullname)
if os.path.isdir(fullname) and not os.path.islink(fullname):
stack.append(fullname)
return files

for file in index("."):
print file

./aifc-example-1.py
./anydbm-example-1.py
./array-example-1.py

如果你不想列出所有的檔案 (基於效能或者是記憶體的考慮) , Example 1-48 展示了另一種方法. 這裡DirectoryWalker 類的行為與序列物件相似, 一次返回一個檔案. (generator?)

1.5.2.3. Example 1-48. 使用 DirectoryWalker 搜尋檔案系統

File: os-path-walk-example-3.py

import os

class DirectoryWalker:
# a forward iterator that traverses a directory tree

def _ _init_ _(self, directory):
    self.stack = [directory]
    self.files = []
    self.index = 0

def _ _getitem_ _(self, index):
    while 1:
        try:
            file = self.files[self.index]
            self.index = self.index + 1
        except IndexError:
            # pop next directory from stack
            self.directory = self.stack.pop()
            self.files = os.listdir(self.directory)
            self.index = 0
        else:
            # got a filename
            fullname = os.path.join(self.directory, file)
            if os.path.isdir(fullname) and not os.path.islink(fullname):
                self.stack.append(fullname)
            return fullname

for file in DirectoryWalker("."):
print file

./aifc-example-1.py
./anydbm-example-1.py
./array-example-1.py

注意 DirectoryWalker 類並不檢查傳遞給 _ _getitem_ _ 方法的索引值. 這意味著如果你越界訪問序列成員(索引數字過大)的話, 這個類將不能正常工作.

最後, 如果你需要處理檔案大小和時間戳, Example 1-49 給出了一個類, 它返回檔名和它的os.stat 屬性(一個元組). 這個版本在每個檔案上都能節省一次或兩次 stat 呼叫( os.path.isdiros.path.islink 內部都使用了 stat ), 並且在一些平臺上執行很快.

1.5.2.4. Example 1-49. 使用 DirectoryStatWalker 搜尋檔案系統

File: os-path-walk-example-4.py

import os, stat

class DirectoryStatWalker:
# a forward iterator that traverses a directory tree, and
# returns the filename and additional file information

def _ _init_ _(self, directory):
    self.stack = [directory]
    self.files = []
    self.index = 0

def _ _getitem_ _(self, index):
    while 1:
        try:
            file = self.files[self.index]
            self.index = self.index + 1
        except IndexError:
            # pop next directory from stack
            self.directory = self.stack.pop()
            self.files = os.listdir(self.directory)
            self.index = 0
        else:
            # got a filename
            fullname = os.path.join(self.directory, file)
            st = os.stat(fullname)
            mode = st[stat.ST_MODE]
            if stat.S_ISDIR(mode) and not stat.S_ISLNK(mode):
                self.stack.append(fullname)
            return fullname, st

for file, st in DirectoryStatWalker("."):
print file, st[stat.ST_SIZE]

./aifc-example-1.py 336
./anydbm-example-1.py 244
./array-example-1.py 526

1.6. stat 模組

Example 1-50 展示了 stat 模組的基本用法, 這個模組包含了一些os.stat 函式中可用的常量和測試函式.

1.6.0.1. Example 1-50. Using the stat Module

File: stat-example-1.py

import stat
import os, time

st = os.stat(“samples/sample.txt”)

print “mode”, “=>”, oct(stat.S_IMODE(st[stat.ST_MODE]))

print “type”, “=>”,
if stat.S_ISDIR(st[stat.ST_MODE]):
print “DIRECTORY”,
if stat.S_ISREG(st[stat.ST_MODE]):
print “REGULAR”,
if stat.S_ISLNK(st[stat.ST_MODE]):
print “LINK”,
print

print “size”, “=>”, st[stat.ST_SIZE]

print “last accessed”, “=>”, time.ctime(st[stat.ST_ATIME])
print “last modified”, “=>”, time.ctime(st[stat.ST_MTIME])
print “inode changed”, “=>”, time.ctime(st[stat.ST_CTIME])

mode => 0664
type => REGULAR
size => 305
last accessed => Sun Oct 10 22:12:30 1999
last modified => Sun Oct 10 18:39:37 1999
inode changed => Sun Oct 10 15:26:38 1999

1.7. string 模組

string 模組提供了一些用於處理字串型別的函式, 如 Example 1-51 所示.

1.7.0.1. Example 1-51. 使用 string 模組

File: string-example-1.py

import string

text = “Monty Python’s Flying Circus”

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 => MONTY PYTHON’S FLYING CIRCUS
lower => monty python’s flying circus
split => [‘Monty’, “Python’s”, ‘Flying’, ‘Circus’]
join => Monty+Python’s+Flying+Circus
replace => Monty Java’s Flying Circus
find => 6 -1
count => 3

在 Python 1.5.2 以及更早版本中, string 使用 strop 中的函式來實現模組功能.

在 Python1.6 和後繼版本,更多的字串操作都可以作為字串方法來訪問, 如 Example 1-52 所示, string 模組中的許多函式只是對相對應字串方法的封裝.

1.7.0.2. Example 1-52. 使用字串方法替代 string 模組函式

File: string-example-2.py

text = “Monty Python’s Flying Circus”

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 => MONTY PYTHON’S FLYING CIRCUS
lower => monty python’s flying circus
split => [‘Monty’, “Python’s”, ‘Flying’, ‘Circus’]
join => Monty+Python’s+Flying+Circus
replace => Monty Perl’s Flying Circus
find => 6 -1
count => 3

為了增強模組對字元的處理能力, 除了字串方法, string 模組還包含了型別轉換函式用於把字串轉換為其他型別, (如 Example 1-53 所示).

1.7.0.3. Example 1-53. 使用 string 模組將字串轉為數字

File: string-example-3.py

import string

print int(“4711”),
print string.atoi(“4711”),
print string.atoi(“11147”, 8), # octal 八進位制
print string.atoi(“1267”, 16), # hexadecimal 十六進位制
print string.atoi(“3mv”, 36) # whatever…

print string.atoi(“4711”, 0),
print string.atoi(“04711”, 0),
print string.atoi(“0x4711”, 0)

print float(“4711”),
print string.atof(“1”),
print string.atof(“1.23e5”)

4711 4711 4711 4711 4711
4711 2505 18193
4711.0 1.0 123000.0

大多數情況下 (特別是當你使用的是1.6及更高版本時) ,你可以使用 intfloat 函式代替 string 模組中對應的函式。

atoi 函式可以接受可選的第二個引數, 指定數基(number base). 如果數基為 0, 那麼函式將檢查字串的前幾個字元來決定使用的數基: 如果為 "0x," 數基將為 16 (十六進位制), 如果為 "0," 則數基為 8 (八進位制). 預設數基值為 10 (十進位制), 當你未傳遞引數時就使用這個值.