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
方法用於新增程式碼, indent
和 dedent
方法用於控制縮排結構. 其他部分交給類來處理.
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"), "<code>", "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 模組
這個模組中的大部分函式通過對應平臺相關模組實現, 比如 posix
和 nt. 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
…
getcwd
和 chdir
函式分別用於獲得和改變當前工作目錄. 如
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
makedirs
和 removedirs
函式用於建立或刪除目錄層,如
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
模組包含了很多可以處理該返回物件的常量及函式. 下面的程式碼展示了其中的一些.
可以使用 chmod
和 utime
函式修改檔案的許可權模式和時間屬性,如
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" ....
). 如果不確定引數的安全性, 那麼最好使用exec
或spawn
代替(稍後介紹).
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
" 才為真.
fork
和 wait
函式在 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-38 給run
函式添加了一個可選的
mode
引數; 當設定為 os.P_NOWAIT
時, 這個指令碼不會等待子程式結束, 預設值os.P_WAIT
時
spawn
會等待子程序結束.
其它的標誌常量還有 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
的函式並且開始查詢程式路徑. 作為最後的選擇, 它會呼叫
exec
和 fork
函式完成工作.
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 檔案, 而不能只是簡單地關閉它們(如果你的程式需要 stdout
或stderr
寫入內容的時候, 可能會出現意想不到的問題).
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/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.isdir
和os.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及更高版本時) ,你可以使用 int
和 float
函式代替
string
模組中對應的函式。
atoi
函式可以接受可選的第二個引數, 指定數基(number base). 如果數基為 0, 那麼函式將檢查字串的前幾個字元來決定使用的數基: 如果為 "0x," 數基將為 16 (十六進位制), 如果為 "0," 則數基為 8 (八進位制). 預設數基值為 10 (十進位制), 當你未傳遞引數時就使用這個值.