本文地址:http://m.survivalescaperooms.com/archimedes/p/python-modules.html,轉載請注明源地址。
如果你退出 Python 解釋器重新進入,以前創建的一切定義(變量和函數)就全部丟失了。因此,如果你想寫一些長久保存的程序,最好使用一個文本編輯器來編寫程序,把保存好的文件輸入解釋器。我們稱之為創建一個腳本。程序變得更長一些了,你可能為了方便維護而把它分離成幾個文件。你也可能想要在幾個程序中都使用一個常用的函數,但是不想把它的定義復制到每一個程序里。
為了滿足這些需要,Python提供了一個方法可以從文件中獲取定義,在腳本或者解釋器的一個交互式實例中使用。這樣的文件被稱為模塊;模塊中的定義可以導入到另一個模塊或主模塊中(在腳本執行時可以調用的變量集位于最高級,并且處于計算器模式)
模塊是包括Python 定義和聲明的文件。文件名就是模塊名加上 .py 后綴。模塊的模塊名(做為一個字符串)可以由全局變量 __name__ 得到。例如,你可以用自己慣用的文件編輯器在當前目錄下創建一個叫 fibo.py 的文件,錄入如下內容:
# Fibonacci numbers moduledef fib(n): # write Fibonacci series up to n a, b = 0, 1 while b < n: PRint b, a, b = b, a+bdef fib2(n): # return Fibonacci series up to n result = [] a, b = 0, 1 while b < n: result.append(b) a, b = b, a+b return result
現在進入Python解釋器,用如下命令導入這個模塊:
>>> import fibo
這樣做不會直接把 fibo中的函數導入當前的語義表;它只是引入了模塊名 fibo。你可以通過模塊名按如下方式訪問這個函數:
>>> fibo.fib(1000)1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987>>> print '/n',fibo.fib2(100)[1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]>>> fibo.__name__'fibo'
如果你想要直接調用函數,通常可以給它賦一個本地名稱:
>>> fib = fibo.fib>>> fib(500)1 1 2 3 5 8 13 21 34 55 89 144 233 377
模塊可以像函數定義一樣包含執行語句。這些語句通常用于初始化模塊。它們只在模塊第一次導入時執行一次。
對應于定義模塊中所有函數的全局語義表,每一個模塊有自己的私有語義表。因此,模塊作者可以在模塊中使用一些全局變量,不會因為與用戶的全局變量沖突而引發錯誤。
另一方面,如果你確定你需要這個,可以像引用模塊中的函數一樣獲取模塊中的全局變量,形如:modname.itemname。
模塊可以導入(import)其它模塊。習慣上所有的 import語句都放在模塊(或腳本,等等)的開頭,但這并不是必須的。被導入的模塊名入在本模塊的全局語義表中。
import 語句的一個變體直接從被導入的模塊中導入命名到本模塊的語義表中。例如:
>>> from fibo import fib, fib2>>> fib(500)1 1 2 3 5 8 13 21 34 55 89 144 233 377
這樣不會從局域語義表中導入模塊名(如上所示, fibo沒有定義)。這樣可以導入所有除了以下劃線(_)開頭的命名。
>>> from fibo import *>>> fib(500)1 1 2 3 5 8 13 21 34 55 89 144 233 377
這樣可以導入所有除了以下劃線(_)開頭的命名。
導入一個叫 spam 的模塊時,解釋器先在當前目錄中搜索名為 spam.py 的文件,然后在環境變量PYTHONPATH 表示的目錄列表中搜索,然后是環境變量PATH 中的路徑列表。如果 PYTHONPATH 沒有設置,或者文件沒有找到,接下來搜索安裝目錄。
實際上,解釋器由 sys.path 變量指定的路徑目錄搜索模塊,該變量初始化時默認包含了輸入腳本(或者當前目錄),PYTHONPATH 和安裝目錄。這樣就允許Python程序(原文如此,programs;我猜想應該是“programer”,程序員--譯者)了解如何修改或替換模塊搜索目錄。需要注意的是由于這些目錄中包含有搜索路徑中運行的腳本,所以這些腳本不應該和標準模塊重名,否則在導入模塊時Python會嘗試把這些腳本當作模塊來加載。這通常會引發一個錯誤。
對于引用了大量標準模塊的短程序,有一個提高啟動速度的重要方法,如果在 spam.py 所在的目錄下存在一個名為 spam.pyc 的文件,它會被視為 spam 模塊的預“編譯”版本。用于創建 spam.pyc 的這一版 spam.py 的修改時間記錄在 spam.pyc 文件中,如果兩者不匹配,.pyc 文件就被忽略。
通常你不需要為創建 spam.pyc 文件做任何工作。一旦 spam.py 成功編譯,就會試圖編譯對應版本的 spam.pyc。如果有任何原因導致寫入不成功,返回的 spam.pyc 文件就會視為無效,隨后即被忽略。 spam.pyc 文件的內容是平臺獨立的,所以Python模塊目錄可以在不同架構的機器之間共享。
部分高級技巧:
以 -O 參數調用Python解釋器時,會生成優化代碼并保存在 .pyo 文件中。現在的優化器沒有太多幫助;它只是刪除了斷言(assert )語句。使用 -O 參參數,所有的代碼都會被優化;.pyc 文件被忽略, .py文件被編譯為優化代碼。
向Python解釋器傳遞兩個 -O 參數(-OO)會執行完全優化的二進制優化編譯,這偶爾會生成錯誤的程序。現在的優化器,只是從二進制代碼中刪除了 __doc__ 符串,生成更為緊湊的 .pyo 文件。因為某些程序依賴于這些變量的可用性,你應該只在確定無誤的場合使用這一選項。
來自 .pyc 文件或 .pyo 文件中的程序不會比來自 .py 文件的運行更快; .pyc 或 .pyo 文件只是在它們加載的時候更快一些。
通過腳本名在命令行運行腳本時,不會將為該腳本創建的二進制代碼寫入 .pyc 或.pyo 文件。當然,把腳本的主要代碼移進一個模塊里,然后用一個小的解構腳本導入這個模塊,就可以提高腳本的啟動速度。也可以直接在命令行中指定一個 .pyc 或 .pyo 文件。
對于同一個模塊(這里指例程 spam.py),可以只有 spam.pyc 文件(或者 spam.pyc ,在使用 -O 參數時)而沒有 spam.py 文件。這樣可以打包發布比較難于逆向工程的Python代碼庫。
模塊可以為指定目錄中的所有模塊創建 .pyc 文件(或者使用 .pyo 參數創建.pyo文件)。
Python帶有一個標準模塊庫,并發布有獨立的文檔,名為 Python 庫參考手冊 (此后稱其為“庫參考手冊”)。有一些模塊內置于解釋器之中,這些操作的訪問接口不是語言內核的一部分,但是已經內置于解釋器了。這既是為了提高效率,也是為了給系統調用等操作系統原生訪問提供接口。這類模塊集合是一個依賴于底層平臺的配置選項。例如,amoeba 模塊只提供對 Amoeba 原生系統的支持。有一個具體的模塊值得注意:sys ,這個模塊內置于所有的Python解釋器。變量 sys.ps1 和 sys.ps2定義了主提示符和副助提示符字符串:
>>> import sys>>> sys.ps1'>>> '>>> sys.ps2'... '>>> sys.ps1 = 'C> 'C> print 'Yuck!'Yuck!C>
這兩個變量只在解釋器的交互模式下有意義。
變量 sys.path 是解釋器模塊搜索路徑的字符串列表。它由環境變量 PYTHONPATH 初始化,如果沒有設定 PYTHONPATH ,就由內置的默認值初始化。你可以用標準的字符串操作修改它:
>>> import sys>>> sys.path.append('/ufs/guido/lib/python')
例1:使用sys模塊
import sysprint 'the command line arguments are:'for i in sys.argv: print iprint '/n/nThe PYTHONPATH is',sys.path, '/n'
運行結果如下:
the command line arguments are:
F:/PycharmProjects/Pytest/test.py
The PYTHONPATH is ['F://PycharmProjects//Pytest', 'C://Python27//lib//site-packages//distribute-0.6.27-py2.7.egg', 'C://Python27//Lib//site-packages//wx-3.0-msw', 'D://chardet-2.3.0', 'F://PycharmProjects//Pytest', 'C://Windows//system32//python27.z
The built-in function dir() is used to find out which names a module defines. It returns a sorted list of strings:
內置函數 dir() 用于按模塊名搜索模塊定義,它返回一個字符串類型的存儲列表:
import fibo,sysprint dir(fibo)print '/n',dir(sys)
運行結果如下:
['__builtins__', '__doc__', '__file__', '__name__', '__package__', 'fib', 'fib2']['__displayhook__', '__doc__', '__egginsert', '__excepthook__', '__name__', '__package__', '__plen', '__stderr__', '__stdin__', '__stdout__', '_clear_type_cache', '_current_frames', '_getframe', '_mercurial', 'api_version', 'argv', 'builtin_module_names', 'byteorder', 'call_tracing', 'callstats', 'copyright', 'displayhook', 'dllhandle', 'dont_write_bytecode', 'exc_clear', 'exc_info', 'exc_type', 'excepthook', 'exec_prefix', 'executable', 'exit', 'flags', 'float_info', 'float_repr_style', 'getcheckinterval', 'getdefaultencoding', 'getfilesystemencoding', 'getprofile', 'getrecursionlimit', 'getrefcount', 'getsizeof', 'gettrace', 'getwindowsversion', 'hexversion', 'long_info', 'maxint', 'maxsize', 'maxunicode', 'meta_path', 'modules', 'path', 'path_hooks', 'path_importer_cache', 'platform', 'prefix', 'py3kwarning', 'setcheckinterval', 'setprofile', 'setrecursionlimit', 'settrace', 'stderr', 'stdin', 'stdout', 'subversion', 'version', 'version_info', 'warnoptions', 'winver']無參數調用時, dir() 函數返回當前定義的命名:
a=[1,2,3,4,5]import fibo,sysfibo=fibo.fibprint dir()
運行結果如下:
['__builtins__', '__doc__', '__file__', '__name__', '__package__', 'a', 'fibo', 'sys']
該列表列出了所有類型的名稱:變量,模塊,函數,等等:
dir() 不會列出內置函數和變量名。如果你想列出這些內容,它們在標準模塊 __builtin__中定義:
>>> import __builtin__>>> dir(__builtin__)
運行結果如下:
['ArithmeticError', 'AssertionError', 'AttributeError', 'BaseException', 'BufferError', 'BytesWarning', 'DeprecationWarning', 'EOFError', 'Ellipsis', 'EnvironmentError', 'Exception', 'False', 'FloatingPointError', 'FutureWarning', 'GeneratorExit', 'IOError', 'ImportError', 'ImportWarning', 'IndentationError', 'IndexError', 'KeyError', 'KeyboardInterrupt', 'LookupError', 'MemoryError', 'NameError', 'None', 'NotImplemented', 'NotImplementedError', 'OSError', 'OverflowError', 'PendingDeprecationWarning', 'ReferenceError', 'RuntimeError', 'RuntimeWarning', 'StandardError', 'StopIteration', 'SyntaxError', 'SyntaxWarning', 'SystemError', 'SystemExit', 'TabError', 'True', 'TypeError', 'UnboundLocalError', 'UnicodeDecodeError', 'UnicodeEncodeError', 'UnicodeError', 'UnicodeTranslateError', 'UnicodeWarning', 'UserWarning', 'ValueError', 'Warning', 'WindowsError', 'ZeroDivisionError', '__debug__', '__doc__', '__import__', '__name__', '__package__', 'abs', 'all', 'any', 'apply', 'basestring', 'bin', 'bool', 'buffer', 'bytearray', 'bytes', 'callable', 'chr', 'classmethod', 'cmp', 'coerce', 'compile', 'complex', 'copyright', 'credits', 'delattr', 'dict', 'dir', 'divmod', 'enumerate', 'eval', 'execfile', 'exit', 'file', 'filter', 'float', 'format', 'frozenset', 'getattr', 'globals', 'hasattr', 'hash', 'help', 'hex', 'id', 'input', 'int', 'intern', 'isinstance', 'issubclass', 'iter', 'len', 'license', 'list', 'locals', 'long', 'map', 'max', 'memoryview', 'min', 'next', 'object', 'oct', 'open', 'ord', 'pow', 'print', 'property', 'quit', 'range', 'raw_input', 'reduce', 'reload', 'repr', 'reversed', 'round', 'set', 'setattr', 'slice', 'sorted', 'staticmethod', 'str', 'sum', 'super', 'tuple', 'type', 'unichr', 'unicode', 'vars', 'xrange', 'zip']
包通常是使用用“圓點模塊名”的結構化模塊命名空間。例如,名為 A.B 的模塊表示了名為 "B" 的包中名為 "A" 的子模塊。正如同用模塊來保存不同的模塊架構可以避免全局變量之間的相互沖突,使用圓點模塊名保存像 NumPy 或 Python Imaging Library 之類的不同類庫架構可以避免模塊之間的命名沖突。
假設你現在想要設計一個模塊集(一個“包”)來統一處理聲音文件和聲音數據。存在幾種不同的聲音格式(通常由它們的擴展名來標識,例如:.wav , .aiff , .au) ),于是,為了在不同類型的文件格式之間轉換,你需要維護一個不斷增長的包集合。可能你還想要對聲音數據做很多不同的操作(例如混音,添加回聲,應用平衡功能,創建一個人造效果),所以你要加入一個無限流模塊來執行這些操作。你的包可能會是這個樣子(通過分級的文件體系來進行分組):
Sound/ Top-level package __init__.py Initialize the sound package Formats/ Subpackage for file format conversions __init__.py wavread.py wavwrite.py aiffread.py aiffwrite.py auread.py auwrite.py ... Effects/ Subpackage for sound effects __init__.py echo.py surround.py reverse.py ... Filters/ Subpackage for filters __init__.py equalizer.py vocoder.py karaoke.py ...導入模塊時,Python通過 sys.path 中的目錄列表來搜索存放包的子目錄。
必須要有一個 __init__.py 文件的存在,才能使Python視該目錄為一個包;這是為了防止某些目錄使用了"string" 這樣的通用名而無意中在隨后的模塊搜索路徑中覆蓋了正確的模塊。最簡單的情況下,__init__.py 可以只是一個空文件,不過它也可能包含了包的初始化代碼,或者設置了 __all__ 變量,后面會有相關介紹。包用戶可以從包中導入合法的模塊,例如:
import Sound.Effects.echo這樣就導入了 Sound.Effects.echo 子模塊。它必需通過完整的名稱來引用。
Sound.Effects.echo.echofilter(input, output, delay=0.7, atten=4)
導入包時有一個可以選擇的方式:
from Sound.Effects import echo
這樣就加載了 echo 子模塊,并且使得它在沒有包前綴的情況下也可以使用,所以它可以如下方式調用:
echo.echofilter(input, output, delay=0.7, atten=4)
還有另一種變體用于直接導入函數或變量:
from Sound.Effects.echo import echofilter
這樣就又一次加載了 echo 子模塊,但這樣就可以直接調用它的 echofilter() 函數:
echofilter(input, output, delay=0.7, atten=4)
需要注意的是使用 from package import item 方式導入包時,這個子項(item)既可以是包中的一個子模塊(或一個子包),也可以是包中定義的其它命名,像函數、類或變量。import 語句首先核對是否包中有這個子項,如果沒有,它假定這是一個模塊,并嘗試加載它。如果沒有找到它,會引發一個 ImportError 異常。
相反,使用類似import item.subitem.subsubitem 這樣的語法時,這些子項必須是包,最后的子項可以是包或模塊,但不能是前面子項中定義的類、函數或變量。
您還可能感興趣:
新聞熱點
疑難解答