python標准庫介紹——10 sys 模塊詳解


==sys 模塊==


``sys`` 模塊提供了許多函數和變量來處理 Python 運行時環境的不同部分.

=== 處理命令行參數===

在解釋器啟動后, ``argv`` 列表包含了傳遞給腳本的所有參數, 如 [Example 1-66 #eg-1-66] 所示. 
列表的第一個元素為腳本自身的名稱.

====Example 1-66. 使用sys模塊獲得腳本的參數====[eg-1-66]

```
File: sys-argv-example-1.py

import sys

print "script name is", sys.argv[0]

if len(sys.argv) > 1:
    print "there are", len(sys.argv)-1, "arguments:"
    for arg in sys.argv[1:]:
        print arg
else:
    print "there are no arguments!"

*B*script name is sys-argv-example-1.py
there are no arguments!*b*
```

如果是從標准輸入讀入腳本 (比如 "``python < sys-argv-example-1.py``"), 
腳本的名稱將被設置為空串. 如果把腳本作為字符串傳遞給python (使用 ``-c`` 選項), 
腳本名會被設置為 "-c".

=== 處理模塊 ===

``path`` 列表是一個由目錄名構成的列表, Python 從中查找擴展模塊( Python 源模塊, 編譯模塊,或者二進制擴展). 
啟動 Python 時,這個列表從根據內建規則, PYTHONPATH 環境變量的內容, 以及注冊表( Windows 系統)等進行初始化. 
由於它只是一個普通的列表, 你可以在程序中對它進行操作, 如 [Example 1-67 #eg-1-67] 所示.

====Example 1-67. 使用sys模塊操作模塊搜索路徑====[eg-1-67]

```
File: sys-path-example-1.py

import sys

print "path has", len(sys.path), "members"

# add the sample directory to the path
sys.path.insert(0, "samples")
import sample

# nuke the path
sys.path = []
import random # oops!

*B*path has 7 members
this is the sample module!
Traceback (innermost last):
  File "sys-path-example-1.py", line 11, in ?
    import random # oops!
ImportError: No module named random*b*
```

``builtin_module_names`` 列表包含 Python 解釋器中所有內建模塊的名稱, [Example 1-68 #eg-1-68] 
 給出了它的樣例代碼.

====Example 1-68. 使用sys模塊查找內建模塊====[eg-1-68]

```
File: sys-builtin-module-names-example-1.py

import sys

def dump(module):
    print module, "=>",
    if module in sys.builtin_module_names:
        print "<BUILTIN>"
    else:
        module = _ _import_ _(module)
        print module._ _file_ _

dump("os")
dump("sys")
dump("string")
dump("strop")
dump("zlib")

*B*os => C:\python\lib\os.pyc
sys => <BUILTIN>
string => C:\python\lib\string.pyc
strop => <BUILTIN>
zlib => C:\python\zlib.pyd*b*
```

``modules`` 字典包含所有加載的模塊. ``import`` 語句在從磁盤導入內容之前會先檢查這個字典.

正如你在 [Example 1-69 #eg-1-69] 中所見到的, Python 在處理你的腳本之前就已經導入了很多模塊.

====Example 1-69. 使用sys模塊查找已導入的模塊====[eg-1-69]

```
File: sys-modules-example-1.py

import sys

print sys.modules.keys()

*B*['os.path', 'os', 'exceptions', '_ _main_ _', 'ntpath', 'strop', 'nt',
'sys', '_ _builtin_ _', 'site', 'signal', 'UserDict', 'string', 'stat']*b*
```

=== 處理引用記數===

``getrefcount`` 函數 (如 [Example 1-70 #eg-1-70] 所示) 返回給定對象的引用記數 - 
也就是這個對象使用次數. Python 會跟蹤這個值, 當它減少為0的時候, 就銷毀這個對象.

====Example 1-70. 使用sys模塊獲得引用記數====[eg-1-70]

```
File: sys-getrefcount-example-1.py

import sys

variable = 1234

print sys.getrefcount(0)
print sys.getrefcount(variable)
print sys.getrefcount(None)

*B*50
3
192*b*
```

注意這個值總是比實際的數量大, 因為該函數本身在確定這個值的時候依賴這個對象.

== 檢查主機平台===

[Example 1-71 #eg-1-71] 展示了 ``platform`` 變量, 它包含主機平台的名稱.

====Example 1-71. 使用sys模塊獲得當前平台====[eg-1-71]

```
File: sys-platform-example-1.py

import sys

#
# emulate "import os.path" (sort of)...

if sys.platform == "win32":
    import ntpath
    pathmodule = ntpath
elif sys.platform == "mac":
    import macpath
    pathmodule = macpath
else:
    # assume it's a posix platform
    import posixpath
    pathmodule = posixpath

print pathmodule
```

典型的平台有Windows 9X/NT(顯示為 ``win32`` ), 以及 Macintosh(顯示為 ``mac`` ) . 
對於 Unix 系統而言, platform 通常來自 "``uname -r``" 命令的輸出, 例如 ``irix6`` , ``linux2`` , 
或者 ``sunos5`` (Solaris).

=== 跟蹤程序===

``setprofiler`` 函數允許你配置一個分析函數(profiling function). 
這個函數會在每次調用某個函數或方法時被調用(明確或隱含的), 
或是遇到異常的時候被調用. 讓我們看看 [Example 1-72 #eg-1-72] 的代碼.

====Example 1-72. 使用sys模塊配置分析函數====[eg-1-72]

```
File: sys-setprofiler-example-1.py

import sys

def test(n):
    j = 0
    for i in range(n):
        j = j + i
    return n

def profiler(frame, event, arg):
    print event, frame.f_code.co_name, frame.f_lineno, "->", arg

# profiler is activated on the next call, return, or exception
# 分析函數將在下次函數調用, 返回, 或異常時激活
sys.setprofile(profiler)

# profile this function call
# 分析這次函數調用
test(1)

# disable profiler
# 禁用分析函數
sys.setprofile(None)

# don't profile this call
# 不會分析這次函數調用
test(2)

*B*call test 3 -> None
return test 7 -> 1*b*
```

基於該函數, ``profile`` 模塊提供了一個完整的分析器框架. 

[Example 1-73 #eg-1-73] 中的 ``settrace`` 函數與此類似, 
但是 ``trace`` 函數會在解釋器每執行到新的一行時被調用.

====Example 1-73. 使用sys模塊配置單步跟蹤函數====[eg-1-73]

```
File: sys-settrace-example-1.py

import sys

def test(n):
    j = 0
    for i in range(n):
        j = j + i
    return n

def tracer(frame, event, arg):
    print event, frame.f_code.co_name, frame.f_lineno, "->", arg
    return tracer

# tracer is activated on the next call, return, or exception
# 跟蹤器將在下次函數調用, 返回, 或異常時激活
sys.settrace(tracer)

# trace this function call
# 跟蹤這次函數調用
test(1)

# disable tracing
# 禁用跟蹤器
sys.settrace(None)

# don't trace this call
# 不會跟蹤這次函數調用
test(2)

*B*call test 3 -> None
line test 3 -> None
line test 4 -> None
line test 5 -> None
line test 5 -> None
line test 6 -> None
line test 5 -> None
line test 7 -> None
return test 7 -> 1*b*
```

基於該函數提供的跟蹤功能, ``pdb`` 模塊提供了完整的調試( debug )框架. 

=== 處理標准輸出/輸入 ===

``stdin`` , ``stdout`` , 以及 ``stderr`` 變量包含與標准 I/O 流對應的流對象. 
如果需要更好地控制輸出,而 ``print`` 不能滿足你的要求, 它們就是你所需要的. 
你也可以 //替換// 它們, 這時候你就可以重定向輸出和輸入到其它設備( device ), 
或者以非標准的方式處理它們. 如 [Example 1-74 #eg-1-74] 所示.

====Example 1-74. 使用sys重定向輸出====[eg-1-74]

```
File: sys-stdout-example-1.py

import sys
import string

class Redirect:

    def _ _init_ _(self, stdout):
        self.stdout = stdout

    def write(self, s):
        self.stdout.write(string.lower(s))

# redirect standard output (including the print statement)
# 重定向標准輸出(包括print語句)
old_stdout = sys.stdout
sys.stdout = Redirect(sys.stdout)

print "HEJA SVERIGE",
print "FRISKT HUM\303\226R"

# restore standard output
# 恢復標准輸出
sys.stdout = old_stdout

print "M\303\205\303\205\303\205\303\205L!"

*B*heja sverige friskt hum\303\266r
M\303\205\303\205\303\205\303\205L!*b*
```

要重定向輸出只要創建一個對象, 並實現它的 ``write`` 方法.

(除非 C 類型的實例外:Python 使用一個叫做 ``softspace`` 的整數屬性來控制輸出中的空白. 
如果沒有這個屬性, Python 將把這個屬性附加到這個對象上. 你不需要在使用 Python 對象時擔心, 
但是在重定向到一個 C 類型時, 你應該確保該類型支持 ``softspace`` 屬性.)

=== 退出程序===

執行至主程序的末尾時,解釋器會自動退出. 但是如果需要中途退出程序, 你可以調用 ``sys.exit`` 函數, 
它帶有一個可選的整數參數返回給調用它的程序. [Example 1-75 #eg-1-75] 給出了范例.

====Example 1-75. 使用sys模塊退出程序====[eg-1-75]

```
File: sys-exit-example-1.py

import sys

print "hello"

sys.exit(1)

print "there"

*B*hello*b*
```

注意 ``sys.exit`` 並不是立即退出. 而是引發一個 //SystemExit// 異常. 
這意味着你可以在主程序中捕獲對 ``sys.exit`` 的調用, 如 [Example 1-76 #eg-1-76] 所示.

====Example 1-76. 捕獲sys.exit調用====[eg-1-76]

```
File: sys-exit-example-2.py

import sys

print "hello"

try:
    sys.exit(1)
except SystemExit:
    pass

print "there"

*B*hello
there*b*
```

如果准備在退出前自己清理一些東西(比如刪除臨時文件), 你可以配置一個 
"退出處理函數"(exit handler), 它將在程序退出的時候自動被調用. 如 [Example 1-77 #eg-1-77] 所示.

====Example 1-77. 另一種捕獲sys.exit調用的方法====[eg-1-77]

```
File: sys-exitfunc-example-1.py

import sys

def exitfunc():
    print "world"

sys.exitfunc = exitfunc

print "hello"
sys.exit(1)
print "there" # never printed # 不會被 print

*B*hello
world*b*
```

在 Python 2.0 以后, 你可以使用 ``atexit`` 模塊來注冊多個退出處理函數.

  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM