Python 2.7 中的新特性¶
- 作者:
A.M. Kuchling (amk at amk.ca)
本文解釋了 Python 2.7 中的新功能。Python 2.7 於 2010 年 7 月 3 日釋出。
數值處理在許多方面都得到了改進,包括浮點數和 Decimal
類。標準庫中增加了一些有用的內容,例如大大增強的 unittest
模組、用於解析命令列選項的 argparse
模組、collections
模組中便捷的 OrderedDict
和 Counter
類,以及許多其他改進。
Python 2.7 計劃成為 2.x 版本的最後一個版本,因此我們致力於使其成為一個長期穩定的版本。為了幫助移植到 Python 3,Python 3.x 系列中的幾個新功能已包含在 2.7 中。
本文不試圖提供新功能的完整規範,而是提供一個方便的概述。有關完整詳情,請參閱 Python 2.7 的文件:https://docs.python.club.tw。如果您想了解設計和實現原理,請參閱特定新功能的 PEP 或 https://bugs.python.org 上討論更改的問題。只要有可能,“Python 新特性”都會連結到每個更改的錯誤/補丁項。
Python 2.x 的未來¶
Python 2.7 是 2.x 系列的最後一個主要版本,因為 Python 維護者已將新功能開發工作的重點轉移到 Python 3.x 系列。這意味著雖然 Python 2 將繼續接收錯誤修復,並進行更新以在新硬體和受支援作業系統版本上正確構建,但語言或標準庫將不再有新的完整功能版本。
然而,儘管 Python 2.7 和 Python 3 之間存在一個大的共同子集,並且遷移到該共同子集或直接遷移到 Python 3 所涉及的許多更改都可以安全地自動化,但其他一些更改(特別是與 Unicode 處理相關的更改)可能需要仔細考慮,最好有健壯的自動化迴歸測試套件,才能有效地遷移。
這意味著 Python 2.7 將長期存在,為尚未移植到 Python 3 的生產系統提供穩定且受支援的基礎平臺。Python 2.7 系列的完整預期生命週期在 PEP 373 中有詳細說明。
2.7 長期意義的一些主要影響是
如上所述,與早期的 2.x 版本相比,2.7 版本的維護週期更長。目前預計 Python 2.7 將至少在 2020 年(在其最初發布 10 年後,而更典型的支援週期為 18-24 個月)之前得到核心開發團隊的支援(接收安全更新和其他錯誤修復)。
隨著 Python 2.7 標準庫的老化,有效利用 Python Package Index(直接或透過重新分發器)對於 Python 2 使用者變得更加重要。除了各種任務的大量第三方包外,可用的包還包括與 Python 2 相容的 Python 3 標準庫中新模組和功能的反向移植,以及各種可以簡化遷移到 Python 3 的工具和庫。Python Packaging User Guide 提供了從 Python Package Index 下載和安裝軟體的指南。
雖然增強 Python 2 的首選方法現在是在 Python Package Index 上釋出新包,但這種方法並非在所有情況下都有效,尤其是在網路安全相關的情況下。在無法透過在 PyPI 上釋出新包或更新包來充分處理的特殊情況下,可以使用 Python 增強提案流程來論證直接將新功能新增到 Python 2 標準庫中。任何此類新增以及新增它們的維護版本都將在下面的 新增到 Python 2.7 維護版本的新功能 部分中註明。
對於希望從 Python 2 遷移到 Python 3 的專案,或者對於希望支援 Python 2 和 Python 3 使用者的庫和框架開發人員,有各種工具和指南可用於幫助確定合適的方法並管理所涉及的一些技術細節。推薦的起點是 如何將 Python 2 程式碼移植到 Python 3 HOWTO 指南。
棄用警告處理方式的更改¶
對於 Python 2.7,做出了政策決定,預設情況下抑制僅開發者關心的警告。DeprecationWarning
及其子類現在被忽略,除非另有要求,從而防止使用者看到應用程式觸發的警告。此更改也已在成為 Python 3.2 的分支中進行。(在 stdlib-sig 上討論並在 bpo-7319 中實施。)
在之前的版本中,DeprecationWarning
訊息預設啟用,為 Python 開發者提供了清晰的指示,表明他們的程式碼在未來的 Python 主要版本中可能會在哪裡中斷。
然而,越來越多的 Python 應用程式使用者不直接參與這些應用程式的開發。DeprecationWarning
訊息與這些使用者無關,這讓他們擔心一個實際正常工作的應用程式,並給應用程式開發者帶來了回應這些擔憂的負擔。
您可以透過使用 -Wdefault
(簡寫:-Wd
)開關執行 Python,或者在執行 Python 之前將 PYTHONWARNINGS
環境變數設定為 "default"
(或 "d"
)來重新啟用 DeprecationWarning
訊息的顯示。Python 程式碼也可以透過呼叫 warnings.simplefilter('default')
來重新啟用它們。
unittest
模組在執行測試時也會自動重新啟用棄用警告。
Python 3.1 功能¶
就像 Python 2.6 包含了 Python 3.0 的功能一樣,2.7 版本也包含了 Python 3.1 中的一些新功能。2.x 系列繼續提供將程式碼遷移到 3.x 系列的工具。
部分反向移植到 2.7 的 3.1 功能列表:
集合字面量的語法(
{1,2,3}
是一個可變集合)。字典和集合推導式(
{i: i*2 for i in range(3)}
)。單個
with
語句中的多個上下文管理器。新版
io
庫,為提高效能而用 C 語言重寫。PEP 372: 將有序字典新增到 collections 中描述的有序字典型別。
PEP 378: 千位分隔符格式說明符 中描述的新
","
格式說明符。memoryview
物件。浮點數
x
的repr()
在許多情況下更短:它現在基於最短的十進位制字串,保證能四捨五入回x
。與 Python 的早期版本一樣,它保證float(repr(x))
能夠恢復x
。浮點數到字串和字串到浮點數的轉換都經過正確舍入。
round()
函式現在也經過正確舍入。PyCapsule
型別,用於為擴充套件模組提供 C API。PyLong_AsLongAndOverflow()
C API 函式。
其他新的 Python3 模式警告包括
operator.isCallable()
和operator.sequenceIncludes()
,它們在 3.x 中不受支援,現在會觸發警告。-3
開關現在自動啟用-Qwarn
開關,它會在對整數和長整數使用經典除法時發出警告。
PEP 372: 向 collections 新增有序字典¶
常規 Python 字典以任意順序迭代鍵/值對。多年來,許多作者編寫了備用實現,這些實現會記住鍵最初插入的順序。基於這些實現的經驗,2.7 在 collections
模組中引入了一個新的 OrderedDict
類。
OrderedDict
API 提供了與常規字典相同的介面,但它根據鍵首次插入的時間以保證的順序迭代鍵和值。
>>> from collections import OrderedDict
>>> d = OrderedDict([('first', 1),
... ('second', 2),
... ('third', 3)])
>>> d.items()
[('first', 1), ('second', 2), ('third', 3)]
如果一個新條目覆蓋了一個現有條目,則原始插入位置保持不變。
>>> d['second'] = 4
>>> d.items()
[('first', 1), ('second', 4), ('third', 3)]
刪除一個條目並重新插入它會將其移動到末尾。
>>> del d['second']
>>> d['second'] = 5
>>> d.items()
[('first', 1), ('third', 3), ('second', 5)]
popitem()
方法有一個可選的 last 引數,預設值為 True
。如果 last 為 true,則返回並移除最近新增的鍵;如果為 false,則選擇最舊的鍵。
>>> od = OrderedDict([(x,0) for x in range(20)])
>>> od.popitem()
(19, 0)
>>> od.popitem()
(18, 0)
>>> od.popitem(last=False)
(0, 0)
>>> od.popitem(last=False)
(1, 0)
比較兩個有序字典會檢查鍵和值,並要求插入順序相同。
>>> od1 = OrderedDict([('first', 1),
... ('second', 2),
... ('third', 3)])
>>> od2 = OrderedDict([('third', 3),
... ('first', 1),
... ('second', 2)])
>>> od1 == od2
False
>>> # Move 'third' key to the end
>>> del od2['third']; od2['third'] = 3
>>> od1 == od2
True
將 OrderedDict
與常規字典進行比較會忽略插入順序,只比較鍵和值。
OrderedDict
是如何工作的?它維護一個鍵的雙向連結串列,在新鍵插入時將其附加到列表中。一個輔助字典將鍵對映到其對應的列表節點,因此刪除無需遍歷整個連結串列,因此仍然是 O(1)。
標準庫現在支援在幾個模組中使用有序字典。
ConfigParser
模組預設使用它們,這意味著現在可以按其原始順序讀取、修改和寫回配置檔案。collections.namedtuple()
的_asdict()
方法現在返回一個有序字典,其值以與底層元組索引相同的順序出現。json
模組的JSONDecoder
類建構函式擴充套件了一個 object_pairs_hook 引數,以允許解碼器構建OrderedDict
例項。還添加了對 PyYAML 等第三方工具的支援。
參見
- PEP 372 - 向 collections 新增有序字典
PEP 由 Armin Ronacher 和 Raymond Hettinger 撰寫;由 Raymond Hettinger 實現。
PEP 378: 千位分隔符格式說明符¶
為了使程式輸出更具可讀性,為大數字新增分隔符可能很有用,將它們顯示為 18,446,744,073,709,551,616 而不是 18446744073709551616。
實現此目的的完全通用解決方案是 locale
模組,它可以使用不同的分隔符(北美為“,”,歐洲為“.”)和不同的分組大小,但是 locale
使用起來很複雜,不適用於不同執行緒為不同區域設定生成輸出的多執行緒應用程式。
因此,在 str.format()
方法使用的小型語言中添加了一個簡單的逗號分組機制。格式化浮點數時,只需在寬度和精度之間包含一個逗號即可。
>>> '{:20,.2f}'.format(18446744073709551616.0)
'18,446,744,073,709,551,616.00'
格式化整數時,在寬度之後包含逗號。
>>> '{:20,d}'.format(18446744073709551616)
'18,446,744,073,709,551,616'
這種機制根本不可修改;逗號總是用作分隔符,分組總是分成三位數。逗號格式化機制不如 locale
模組通用,但它更容易使用。
參見
- PEP 378 - 千位分隔符格式說明符
PEP 由 Raymond Hettinger 撰寫;由 Eric Smith 實現。
PEP 389: 用於解析命令列的 argparse 模組¶
用於解析命令列引數的 argparse
模組被新增,作為 optparse
模組更強大的替代品。
這意味著 Python 現在支援三個不同的模組來解析命令列引數:getopt
、optparse
和 argparse
。getopt
模組與 C 庫的 getopt()
函式非常相似,因此如果您正在編寫最終將用 C 重寫的 Python 原型,它仍然很有用。optparse
變得多餘,但沒有計劃將其刪除,因為仍有許多指令碼在使用它,而且沒有自動化方法來更新這些指令碼。(使 argparse
API 與 optparse
的介面保持一致曾被討論但被拒絕,因為太混亂和困難。)
簡而言之,如果您正在編寫新指令碼並且不需要擔心與早期 Python 版本的相容性,請使用 argparse
而不是 optparse
。
這是一個例子
import argparse
parser = argparse.ArgumentParser(description='Command-line example.')
# Add optional switches
parser.add_argument('-v', action='store_true', dest='is_verbose',
help='produce verbose output')
parser.add_argument('-o', action='store', dest='output',
metavar='FILE',
help='direct output to FILE instead of stdout')
parser.add_argument('-C', action='store', type=int, dest='context',
metavar='NUM', default=0,
help='display NUM lines of added context')
# Allow any number of additional arguments.
parser.add_argument(nargs='*', action='store', dest='inputs',
help='input filenames (default is stdin)')
args = parser.parse_args()
print args.__dict__
除非您覆蓋它,否則 -h
和 --help
開關會自動新增,並生成格式整齊的輸出。
-> ./python.exe argparse-example.py --help
usage: argparse-example.py [-h] [-v] [-o FILE] [-C NUM] [inputs [inputs ...]]
Command-line example.
positional arguments:
inputs input filenames (default is stdin)
optional arguments:
-h, --help show this help message and exit
-v produce verbose output
-o FILE direct output to FILE instead of stdout
-C NUM display NUM lines of added context
與 optparse
一樣,命令列開關和引數作為具有由 dest 引數命名的屬性的物件返回。
-> ./python.exe argparse-example.py -v
{'output': None,
'is_verbose': True,
'context': 0,
'inputs': []}
-> ./python.exe argparse-example.py -v -o /tmp/output -C 4 file1 file2
{'output': '/tmp/output',
'is_verbose': True,
'context': 4,
'inputs': ['file1', 'file2']}
argparse
比 optparse
有更復雜的驗證;您可以將精確數量的引數指定為整數,透過傳遞 '*'
指定 0 個或更多引數,透過傳遞 '+'
指定 1 個或更多引數,或者透過 '?'
指定一個可選引數。頂級解析器可以包含子解析器來定義具有不同開關集的子命令,例如 svn commit
、svn checkout
等。您可以將引數型別指定為 FileType
,它將自動為您開啟檔案並理解 '-'
表示標準輸入或輸出。
參見
argparse
文件argparse 模組的文件頁面。
- 將 optparse 程式碼遷移到 argparse
Python 文件的一部分,描述瞭如何轉換使用
optparse
的程式碼。- PEP 389 - argparse - 新命令列解析模組
PEP 由 Steven Bethard 撰寫並實現。
PEP 391: 基於字典的日誌配置¶
logging
模組非常靈活;應用程式可以定義一個日誌子系統樹,並且此樹中的每個日誌記錄器都可以過濾掉某些訊息、以不同方式格式化它們並將訊息定向到不同數量的處理程式。
所有這些靈活性可能需要大量的配置。您可以編寫 Python 語句來建立物件並設定其屬性,但複雜的設定需要冗長但枯燥的程式碼。logging
還支援一個解析檔案的 fileConfig()
函式,但檔案格式不支援配置過濾器,並且透過程式設計生成它會更混亂。
Python 2.7 添加了一個 dictConfig()
函式,它使用字典來配置日誌。有許多方法可以從不同來源生成字典:使用程式碼構建一個;解析包含 JSON 的檔案;或者如果安裝了 YAML 解析庫,則使用它。有關更多資訊,請參閱 配置函式。
以下示例配置了兩個日誌記錄器,根日誌記錄器和名為“network”的日誌記錄器。傳送到根日誌記錄器的訊息將使用 syslog 協議傳送到系統日誌,傳送到“network”日誌記錄器的訊息將寫入 network.log
檔案,該檔案將在日誌達到 1MB 時進行輪換。
import logging
import logging.config
configdict = {
'version': 1, # Configuration schema in use; must be 1 for now
'formatters': {
'standard': {
'format': ('%(asctime)s %(name)-15s '
'%(levelname)-8s %(message)s')}},
'handlers': {'netlog': {'backupCount': 10,
'class': 'logging.handlers.RotatingFileHandler',
'filename': '/logs/network.log',
'formatter': 'standard',
'level': 'INFO',
'maxBytes': 1000000},
'syslog': {'class': 'logging.handlers.SysLogHandler',
'formatter': 'standard',
'level': 'ERROR'}},
# Specify all the subordinate loggers
'loggers': {
'network': {
'handlers': ['netlog']
}
},
# Specify properties of the root logger
'root': {
'handlers': ['syslog']
},
}
# Set up configuration
logging.config.dictConfig(configdict)
# As an example, log two error messages
logger = logging.getLogger('/')
logger.error('Database not found')
netlogger = logging.getLogger('network')
netlogger.error('Connection failed')
對 logging
模組的三個較小增強功能,均由 Vinay Sajip 實現:
SysLogHandler
類現在支援透過 TCP 進行系統日誌記錄。建構函式有一個 socktype 引數,指定要使用的套接字型別,可以是用於 UDP 的socket.SOCK_DGRAM
或用於 TCP 的socket.SOCK_STREAM
。預設協議仍然是 UDP。Logger
例項獲得了一個getChild()
方法,該方法使用相對路徑檢索子日誌記錄器。例如,一旦您透過執行log = getLogger('app')
檢索到日誌記錄器,呼叫log.getChild('network.listen')
等效於getLogger('app.network.listen')
。LoggerAdapter
類獲得了一個isEnabledFor()
方法,該方法接受一個 level 並返回底層日誌記錄器是否會處理該重要級別的訊息。
參見
- PEP 391 - 基於字典的日誌配置
PEP 由 Vinay Sajip 撰寫並實現。
PEP 3106: 字典檢視¶
字典方法 keys()
、values()
和 items()
在 Python 3.x 中有所不同。它們返回一個稱為 檢視 的物件,而不是完全具體化的列表。
在 Python 2.7 中不可能更改 keys()
、values()
和 items()
的返回值,因為這會破壞太多程式碼。相反,3.x 版本以新名稱 viewkeys()
、viewvalues()
和 viewitems()
新增。
>>> d = dict((i*10, chr(65+i)) for i in range(26))
>>> d
{0: 'A', 130: 'N', 10: 'B', 140: 'O', 20: ..., 250: 'Z'}
>>> d.viewkeys()
dict_keys([0, 130, 10, 140, 20, 150, 30, ..., 250])
檢視可以迭代,但鍵和項檢視也像集合一樣。 &
運算子執行交集,而 |
執行並集。
>>> d1 = dict((i*10, chr(65+i)) for i in range(26))
>>> d2 = dict((i**.5, i) for i in range(1000))
>>> d1.viewkeys() & d2.viewkeys()
set([0.0, 10.0, 20.0, 30.0])
>>> d1.viewkeys() | range(0, 30)
set([0, 1, 130, 3, 4, 5, 6, ..., 120, 250])
檢視會跟蹤字典,並且其內容會隨著字典的修改而更改。
>>> vk = d.viewkeys()
>>> vk
dict_keys([0, 130, 10, ..., 250])
>>> d[260] = '&'
>>> vk
dict_keys([0, 130, 260, 10, ..., 250])
但是,請注意,在迭代檢視時不能新增或刪除鍵。
>>> for k in vk:
... d[k*2] = k
...
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
RuntimeError: dictionary changed size during iteration
您可以在 Python 2.x 程式碼中使用檢視方法,並且 2to3 轉換器會將它們更改為標準的 keys()
、values()
和 items()
方法。
PEP 3137: memoryview 物件¶
memoryview
物件提供了另一個物件的記憶體內容的檢視,該檢視與 bytes
型別的介面匹配。
>>> import string
>>> m = memoryview(string.letters)
>>> m
<memory at 0x37f850>
>>> len(m) # Returns length of underlying object
52
>>> m[0], m[25], m[26] # Indexing returns one byte
('a', 'z', 'A')
>>> m2 = m[0:26] # Slicing returns another memoryview
>>> m2
<memory at 0x37f080>
檢視的內容可以轉換為位元組字串或整數列表。
>>> m2.tobytes()
'abcdefghijklmnopqrstuvwxyz'
>>> m2.tolist()
[97, 98, 99, 100, 101, 102, 103, ... 121, 122]
>>>
memoryview
物件允許修改底層物件,如果它是一個可變物件。
>>> m2[0] = 75
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: cannot modify read-only memory
>>> b = bytearray(string.letters) # Creating a mutable object
>>> b
bytearray(b'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ')
>>> mb = memoryview(b)
>>> mb[0] = '*' # Assign to view, changing the bytearray.
>>> b[0:5] # The bytearray has been changed.
bytearray(b'*bcde')
>>>
其他語言更改¶
對核心 Python 語言做了一些較小的更改
集合字面量的語法已從 Python 3.x 反向移植。花括號用於包圍結果可變集合的內容;集合字面量透過不包含冒號和值來與字典區分。
{}
繼續表示一個空字典;使用set()
表示一個空集合。>>> {1, 2, 3, 4, 5} set([1, 2, 3, 4, 5]) >>> set() # empty set set([]) >>> {} # empty dict {}
由 Alexandre Vassalotti 反向移植;bpo-2335。
字典和集合推導式是從 3.x 反向移植的另一個功能,它將列表/生成器推導式推廣到使用集合和字典的字面量語法。
>>> {x: x*x for x in range(6)} {0: 0, 1: 1, 2: 4, 3: 9, 4: 16, 5: 25} >>> {('a'*x) for x in range(6)} set(['', 'a', 'aa', 'aaa', 'aaaa', 'aaaaa'])
由 Alexandre Vassalotti 反向移植;bpo-2333。
with
語句現在可以在一個語句中使用多個上下文管理器。上下文管理器從左到右處理,每個管理器都被視為開始一個新的with
語句。這意味著with A() as a, B() as b: ... suite of statements ...
等價於
with A() as a: with B() as b: ... suite of statements ...
contextlib.nested()
函式提供了非常相似的功能,因此它不再是必需的,並且已被棄用。(在 https://codereview.appspot.com/53094 中提出;由 Georg Brandl 實現。)
浮點數和字串之間的轉換現在在大多數平臺上都進行了正確舍入。這些轉換髮生在許多不同的地方:浮點數和複數上的
str()
;float
和complex
建構函式;數字格式化;使用marshal
、pickle
和json
模組序列化和反序列化浮點數和複數;Python 程式碼中浮點數和虛數字面量的解析;以及Decimal
到浮點數的轉換。與此相關的是,浮點數 *x* 的
repr()
現在返回一個基於最短十進位制字串的結果,該字串保證在正確舍入(使用 round-half-to-even 舍入模式)下能捨入回 *x*。以前它返回一個基於將 x 舍入到 17 位小數的字串。負責此改進的舍入庫在 Windows 和使用 gcc、icc 或 suncc 編譯器的 Unix 平臺上工作。可能有一些平臺無法保證此程式碼的正確執行,因此此類系統上不使用此程式碼。您可以透過檢查
sys.float_repr_style
來找出正在使用的程式碼,如果使用新程式碼,它將是short
,否則為legacy
。由 Eric Smith 和 Mark Dickinson 實現,使用 David Gay 的
dtoa.c
庫;bpo-7117。長整數和常規整數到浮點數的轉換現在以不同的方式舍入,返回最接近該數字的浮點數。對於可以精確轉換的小整數來說,這並不重要,但對於不可避免地會損失精度的大數字,Python 2.7 現在更接近地進行近似。例如,Python 2.6 計算以下結果:
>>> n = 295147905179352891391 >>> float(n) 2.9514790517935283e+20 >>> n - long(float(n)) 65535L
Python 2.7 的浮點結果更大,但更接近真實值。
>>> n = 295147905179352891391 >>> float(n) 2.9514790517935289e+20 >>> n - long(float(n)) -1L
(由 Mark Dickinson 實現;bpo-3166。)
整數除法在舍入行為上也更精確。(也由 Mark Dickinson 實現;bpo-1811。)
複數的隱式強制轉換已移除;直譯器將不再嘗試呼叫複數物件的
__coerce__()
方法。(由 Meador Inge 和 Mark Dickinson 移除;bpo-5211。)str.format()
方法現在支援替換欄位的自動編號。這使得使用str.format()
更接近於使用%s
格式化。>>> '{}:{}:{}'.format(2009, 04, 'Sunday') '2009:4:Sunday' >>> '{}:{}:{day}'.format(2009, 4, day='Sunday') '2009:4:Sunday'
自動編號從左到右取欄位,因此第一個
{...}
說明符將使用str.format()
的第一個引數,下一個說明符將使用下一個引數,依此類推。您不能混合自動編號和顯式編號——要麼對所有說明符欄位編號,要麼都不編號——但您可以混合自動編號和命名欄位,如上面的第二個示例所示。(由 Eric Smith 貢獻;bpo-5237。)複數現在正確支援與
format()
的使用,並預設為右對齊。指定精度或逗號分隔適用於數字的實部和虛部,但指定的欄位寬度和對齊方式適用於結果1.5+3j
輸出的整體。(由 Eric Smith 貢獻;bpo-1588 和 bpo-7988。)“F”格式程式碼現在總是使用大寫字元格式化其輸出,因此它現在將生成“INF”和“NAN”。(由 Eric Smith 貢獻;bpo-3382。)
一個低階更改:如果
object.__format__()
方法傳入了格式字串,它現在會觸發一個PendingDeprecationWarning
,因為object
的__format__()
方法會將物件轉換為字串表示形式並格式化該字串。以前,該方法會靜默地將格式字串應用於字串表示形式,但這可能會隱藏 Python 程式碼中的錯誤。如果您提供了格式資訊(例如對齊或精度),那麼您可能期望格式化以某種特定於物件的方式應用。(由 Eric Smith 修復;bpo-7994。)int()
和long()
型別獲得了一個bit_length
方法,該方法返回表示其引數所需的位數(以二進位制形式)>>> n = 37 >>> bin(n) '0b100101' >>> n.bit_length() 6 >>> n = 2**123-1 >>> n.bit_length() 123 >>> (n+1).bit_length() 124
(由 Fredrik Johansson 和 Victor Stinner 貢獻;bpo-3439。)
如果相對匯入(例如
from .os import sep
)失敗,import
語句將不再嘗試絕對匯入。這修復了一個 bug,但也可能破壞某些偶然工作的import
語句。(由 Meador Inge 修復;bpo-7902。)現在,內建
unicode
型別的一個子類可以覆蓋__unicode__()
方法。(由 Victor Stinner 實現;bpo-1583863。)bytearray
型別的translate()
方法現在接受None
作為其第一個引數。(由 Georg Brandl 修復;bpo-4759。)當使用
@classmethod
和@staticmethod
將方法包裝為類方法或靜態方法時,包裝器物件現在將其__func__
屬性公開為包裝函式。(由 Amaury Forgeot d’Arc 貢獻,根據 George Sakkis 的建議;bpo-5982。)當使用
__slots__
設定了一組受限的屬性時,刪除未設定的屬性不會像您預期那樣引發AttributeError
。Benjamin Peterson 修復了此問題;bpo-7604。)現在支援兩種新編碼:“cp720”,主要用於阿拉伯文字;以及“cp858”,CP 850 的一個變體,增加了歐元符號。(CP720 由 Alexander Belchenko 和 Amaury Forgeot d’Arc 在 bpo-1616979 中貢獻;CP858 由 Tim Hatch 在 bpo-8016 中貢獻。)
file
物件現在在 POSIX 平臺上嘗試開啟目錄時,會在IOError
異常上設定filename
屬性(Jan Kaliszewski 指出;bpo-4764),並且現在明確檢查並禁止寫入只讀檔案物件,而不是信任 C 庫捕獲並報告錯誤(Stefan Krah 修復;bpo-5677)。Python 詞法分析器現在自行轉換行尾,因此內建函式
compile()
現在接受使用任何行尾約定的程式碼。此外,它不再要求程式碼以換行符結尾。在 Python 3.x 中,函式定義中的額外括號是非法的,這意味著
def f((x)): pass
會導致語法錯誤。在 Python3-warning 模式下,Python 2.7 現在會對此奇怪用法發出警告。(James Lingard 指出;bpo-7362。)現在可以建立對舊式類物件的弱引用。新式類總是可以弱引用的。(由 Antoine Pitrou 修復;bpo-8268。)
當模組物件被垃圾回收時,只有當沒有其他物件持有對該模組字典的引用時,該字典才會被清除(bpo-7140)。
直譯器更改¶
一個新的環境變數 PYTHONWARNINGS
允許控制警告。它應該設定為一個包含警告設定的字串,等同於與 -W
開關一起使用的設定,用逗號分隔。(由 Brian Curtin 貢獻;bpo-7301。)
例如,以下設定將每次發生警告時列印警告,但將 Cookie
模組的警告轉換為錯誤。(設定環境變數的確切語法因作業系統和 shell 而異。)
export PYTHONWARNINGS=all,error:::Cookie:0
最佳化¶
已新增多個性能增強
添加了一個新的操作碼來執行
with
語句的初始設定,查詢__enter__()
和__exit__()
方法。(由 Benjamin Peterson 貢獻。)垃圾收集器現在對於一種常見的使用模式表現更好:當分配了許多物件而沒有釋放任何物件時。以前,這會花費二次時間進行垃圾收集,但現在,隨著堆上物件數量的增長,完整垃圾收集的次數減少了。新的邏輯僅在中間代收集 10 次且中間代的倖存物件數量超過最老代物件數量的 10% 時才執行完整的垃圾收集過程。(由 Martin von Löwis 建議,Antoine Pitrou 實現;bpo-4074。)
垃圾收集器試圖避免跟蹤不能構成迴圈的簡單容器。在 Python 2.7 中,這對於包含原子型別(如整數、字串等)的元組和字典現在是成立的。因此,包含原子型別元組的字典也不會被跟蹤。這有助於透過減少收集器需要考慮和遍歷的物件數量來降低每次垃圾收集的成本。(由 Antoine Pitrou 貢獻;bpo-4688。)
長整數現在內部儲存為以
2**15
為基數或以2**30
為基數,基數在構建時確定。以前,它們總是以2**15
為基數儲存。使用2**30
為基數在 64 位機器上提供了顯著的效能改進,但在 32 位機器上的基準測試結果好壞參半。因此,預設情況下,在 64 位機器上使用2**30
為基數,在 32 位機器上使用2**15
為基數;在 Unix 上,有一個新的配置選項--enable-big-digits
可用於覆蓋此預設值。除了效能改進之外,此更改對終端使用者應該是不可見的,只有一個例外:為了測試和除錯目的,有一個新的 structseq
sys.long_info
,它提供有關內部格式的資訊,給出每個數字的位數以及用於儲存每個數字的 C 型別的大小(以位元組為單位)。>>> import sys >>> sys.long_info sys.long_info(bits_per_digit=30, sizeof_digit=4)
(由 Mark Dickinson 貢獻;bpo-4258。)
另一組更改使長物件小了幾字節:在 32 位系統上小 2 位元組,在 64 位系統上小 6 位元組。(由 Mark Dickinson 貢獻;bpo-5260。)
長整數的除法演算法透過收緊內部迴圈、使用移位而不是乘法以及修復不必要的額外迭代而變得更快。各種基準測試顯示長整數除法和取模運算的速度提高了 50% 到 150%。(由 Mark Dickinson 貢獻;bpo-5512。)按位運算也顯著加快(最初的補丁由 Gregory Smith 貢獻;bpo-1087418)。
%
的實現會檢查左側運算元是否為 Python 字串並進行特殊處理;這使得頻繁使用%
處理字串的應用程式(例如模板庫)的效能提高了 1-3%。(由 Collin Winter 實現;bpo-5176。)帶有
if
條件的列表推導式被編譯成更快的位元組碼。(由 Antoine Pitrou 提交補丁,Jeffrey Yasskin 反向移植到 2.7;bpo-4715。)將整數或長整數轉換為十進位制字串的速度加快了,方法是特殊處理基數 10,而不是使用支援任意基數的通用轉換函式。(Gawain Bolton 貢獻補丁;bpo-6713。)
字串類型別(字串、Unicode 字串和
bytearray
物件)的split()
、replace()
、rindex()
、rpartition()
和rsplit()
方法現在使用快速反向搜尋演算法而不是逐字元掃描。這有時速度提高 10 倍。(由 Florent Xicluna 新增;bpo-7462 和 bpo-7622。)pickle
和cPickle
模組現在會自動對用於屬性名的字串進行內部化,從而減少解構後物件的記憶體使用。(由 Jake McGuire 貢獻;bpo-5084。)cPickle
模組現在特殊處理字典,將序列化它們所需的時間縮短了近一半。(由 Collin Winter 貢獻;bpo-5670。)
新增和改進的模組¶
與每個版本一樣,Python 的標準庫獲得了一些增強和錯誤修復。以下是按模組名稱字母順序排序的最值得注意的更改的部分列表。有關更完整的更改列表,請查閱源樹中的 Misc/NEWS
檔案,或檢視 Subversion 日誌以獲取所有詳細資訊。
bdb
模組的基類除錯類Bdb
獲得了跳過模組的功能。建構函式現在接受一個可迭代物件,其中包含 glob 樣式的模式,例如django.*
;偵錯程式將不會進入與這些模式之一匹配的模組的堆疊幀。(由 Maru Newby 根據 Senthil Kumaran 的建議貢獻;bpo-5142。)binascii
模組現在支援緩衝區 API,因此可以與memoryview
例項和其他類似的緩衝區物件一起使用。(由 Florent Xicluna 從 3.x 反向移植;bpo-7703。)更新模組:
bsddb
模組已從 4.7.2devel9 更新到 pybsddb 包 的 4.8.4 版本。新版本具有更好的 Python 3.x 相容性、各種錯誤修復,並添加了幾個新的 BerkeleyDB 標誌和方法。(由 Jesús Cea Avión 更新;bpo-8156。pybsddb 的更新日誌可以在 https://hg.jcea.es/pybsddb/file/tip/ChangeLog 處閱讀。)bz2
模組的BZ2File
現在支援上下文管理協議,因此您可以編寫with bz2.BZ2File(...) as f:
。(由 Hagen Fürstenau 貢獻;bpo-3860。)新類:
collections
模組中的Counter
類對於統計資料很有用。Counter
例項的行為大部分像字典,但對於缺失的鍵返回零而不是引發KeyError
。>>> from collections import Counter >>> c = Counter() >>> for letter in 'here is a sample of english text': ... c[letter] += 1 ... >>> c Counter({' ': 6, 'e': 5, 's': 3, 'a': 2, 'i': 2, 'h': 2, 'l': 2, 't': 2, 'g': 1, 'f': 1, 'm': 1, 'o': 1, 'n': 1, 'p': 1, 'r': 1, 'x': 1}) >>> c['e'] 5 >>> c['z'] 0
還有三個附加的
Counter
方法。most_common()
返回 N 個最常見的元素及其計數。elements()
返回一個迭代器,遍歷所包含的元素,每個元素重複多次,次數與其計數相同。subtract()
接受一個可迭代物件,併為每個元素減去一,而不是新增;如果引數是字典或另一個Counter
,則減去計數。>>> c.most_common(5) [(' ', 6), ('e', 5), ('s', 3), ('a', 2), ('i', 2)] >>> c.elements() -> 'a', 'a', ' ', ' ', ' ', ' ', ' ', ' ', 'e', 'e', 'e', 'e', 'e', 'g', 'f', 'i', 'i', 'h', 'h', 'm', 'l', 'l', 'o', 'n', 'p', 's', 's', 's', 'r', 't', 't', 'x' >>> c['e'] 5 >>> c.subtract('very heavy on the letter e') >>> c['e'] # Count is now lower -1
由 Raymond Hettinger 貢獻;bpo-1696199。
新類:
OrderedDict
在前面的 PEP 372: 向 collections 新增有序字典 部分中進行了描述。新方法:
deque
資料型別現在有一個count()
方法,該方法返回與提供的引數 x 相等的元素數量,以及一個reverse()
方法,該方法就地反轉雙端佇列的元素。deque
還將其最大長度公開為只讀的maxlen
屬性。(兩項功能均由 Raymond Hettinger 新增。)namedtuple
類現在有一個可選的 rename 引數。如果 rename 為 true,則因重複或不是合法的 Python 識別符號而無效的欄位名將被重新命名為從欄位列表中欄位位置派生的合法名稱。>>> from collections import namedtuple >>> T = namedtuple('T', ['field1', '$illegal', 'for', 'field2'], rename=True) >>> T._fields ('field1', '_1', '_2', 'field2')
(由 Raymond Hettinger 新增;bpo-1818。)
最後,如果將對映與非
Mapping
的其他型別進行比較,則Mapping
抽象基類現在返回NotImplemented
。(由 Daniel Stutzbach 修復;bpo-8729。)ConfigParser
模組中解析類的建構函式現在接受一個 allow_no_value 引數,預設為 false;如果為 true,則允許沒有值的選項。例如>>> import ConfigParser, StringIO >>> sample_config = """ ... [mysqld] ... user = mysql ... pid-file = /var/run/mysqld/mysqld.pid ... skip-bdb ... """ >>> config = ConfigParser.RawConfigParser(allow_no_value=True) >>> config.readfp(StringIO.StringIO(sample_config)) >>> config.get('mysqld', 'user') 'mysql' >>> print config.get('mysqld', 'skip-bdb') None >>> print config.get('mysqld', 'unknown') Traceback (most recent call last): ... NoOptionError: No option 'unknown' in section: 'mysqld'
(由 Mats Kindahl 貢獻;bpo-7005。)
已棄用函式:
contextlib.nested()
,它允許使用單個with
語句處理多個上下文管理器,已棄用,因為with
語句現在支援多個上下文管理器。cookielib
模組現在會忽略版本欄位無效的 cookie,即不包含整數值的 cookie。(由 John J. Lee 修復;bpo-3924。)copy
模組的deepcopy()
函式現在將正確複製繫結的例項方法。(由 Robert Collins 實現;bpo-1515。)ctypes
模組現在總是將None
轉換為 C 的NULL
指標,用於宣告為指標的引數。(由 Thomas Heller 更改;bpo-4606。)底層 libffi 庫 已更新到版本 3.0.9,其中包含針對不同平臺的各種修復。(由 Matthias Klose 更新;bpo-8142。)新方法:
datetime
模組的timedelta
類增加了一個total_seconds()
方法,該方法返回持續時間的秒數。(由 Brian Quinlan 貢獻;bpo-5788。)新方法:
Decimal
類增加了一個from_float()
類方法,該方法執行浮點數到Decimal
的精確轉換。這種精確轉換力求最接近浮點表示值的十進位制近似值;因此,得到的十進位制值仍將包含不準確性(如果有)。例如,Decimal.from_float(0.1)
返回Decimal('0.1000000000000000055511151231257827021181583404541015625')
。(由 Raymond Hettinger 實現;bpo-4796。)現在,將
Decimal
例項與浮點數進行比較會根據運算元的數值產生合理的結果。以前,此類比較會回退到 Python 比較物件的預設規則,該規則會根據它們的型別產生任意結果。請注意,您仍然不能在其他操作(例如加法)中將Decimal
和浮點數結合使用,因為您應該明確選擇如何在浮點數和Decimal
之間進行轉換。(由 Mark Dickinson 修復;bpo-2531。)Decimal
的建構函式現在接受浮點數(由 Raymond Hettinger 新增;bpo-8257)和非歐洲 Unicode 字元,例如阿拉伯語-印度數字(由 Mark Dickinson 貢獻;bpo-6595)。Context
類的許多方法現在接受整數和Decimal
例項;唯一的例外是canonical()
和is_canonical()
方法。(由 Juan José Conti 提供補丁;bpo-7633。)當使用
Decimal
例項與字串的format()
方法時,預設對齊方式以前是左對齊。這已更改為右對齊,這對於數字型別更合理。(由 Mark Dickinson 更改;bpo-6857。)涉及信令 NaN 值(或
sNAN
)的比較現在會發出InvalidOperation
訊號,而不是根據比較運算子靜默返回 true 或 false 值。靜默 NaN 值(或NaN
)現在是可雜湊的。(由 Mark Dickinson 修復;bpo-7279。)difflib
模組現在透過一個小的更改產生與現代 diff/patch 工具更相容的輸出,在提供檔名的頭中使用製表符而不是空格作為分隔符。(由 Anatoly Techtonik 修復;bpo-7585。)Distutils 的
sdist
命令現在總是重新生成MANIFEST
檔案,因為即使MANIFEST.in
或setup.py
檔案未被修改,使用者也可能建立了一些應該包含的新檔案。(由 Tarek Ziadé 修復;bpo-8688。)doctest
模組的IGNORE_EXCEPTION_DETAIL
標誌現在將忽略包含正在測試的異常的模組名稱。(由 Lennart Regebro 提供補丁;bpo-7490。)email
模組的Message
類現在將接受 Unicode 值的有效載荷,自動將有效載荷轉換為output_charset
指定的編碼。(由 R. David Murray 新增;bpo-1368247。)Fraction
類現在接受單個浮點數或Decimal
例項,或兩個有理數,作為其建構函式的引數。(由 Mark Dickinson 實現;有理數在 bpo-5812 中新增,浮點數/十進位制數在 bpo-8294 中新增。)分數和複數之間的排序比較(
<
、<=
、>
、>=
)現在會引發TypeError
。這修復了一個疏忽,使Fraction
與其他數字型別匹配。新類:
FTP_TLS
在ftplib
模組中,提供使用 TLS 封裝身份驗證以及後續控制和資料傳輸的安全 FTP 連線。(由 Giampaolo Rodola 貢獻;bpo-2054。)用於二進位制上傳的
storbinary()
方法現在可以透過新增 rest 引數來重新啟動上傳(由 Pablo Mouzo 提供補丁;bpo-6845)。新類裝飾器:
total_ordering()
在functools
模組中,接受定義了__eq__()
方法和__lt__()
、__le__()
、__gt__()
或__ge__()
之一的類,並生成缺失的比較方法。由於__cmp__()
方法在 Python 3.x 中已被棄用,此裝飾器使得定義有序類更加容易。(由 Raymond Hettinger 新增;bpo-5479。)新函式:
cmp_to_key()
將接受一個期望兩個引數的舊式比較函式,並返回一個新的可呼叫物件,該物件可用作sorted()
、min()
和max()
等函式的 key 引數。主要目的是幫助使程式碼與 Python 3.x 相容。(由 Raymond Hettinger 新增。)新函式:
gc
模組的is_tracked()
如果給定例項被垃圾收集器跟蹤則返回 true,否則返回 false。(由 Antoine Pitrou 貢獻;bpo-4688。)gzip
模組的GzipFile
現在支援上下文管理協議,因此您可以編寫with gzip.GzipFile(...) as f:
(由 Hagen Fürstenau 貢獻;bpo-3860),並且它現在實現了io.BufferedIOBase
ABC,因此您可以用io.BufferedReader
包裝它以加快處理速度(由 Nir Aides 貢獻;bpo-7471)。現在還可以透過向建構函式提供可選的時間戳來覆蓋 gzipped 檔案中記錄的修改時間。(由 Jacques Frechet 貢獻;bpo-4272。)gzip 格式的檔案可以用尾部零位元組填充;
gzip
模組現在將消耗這些尾部位元組。(由 Tadek Pietraszek 和 Brian Curtin 修復;bpo-2846。)新屬性:
hashlib
模組現在有一個algorithms
屬性,其中包含一個元組,命名了支援的演算法。在 Python 2.7 中,hashlib.algorithms
包含('md5', 'sha1', 'sha224', 'sha256', 'sha384', 'sha512')
。(由 Carl Chenet 貢獻;bpo-7418。)httplib
模組使用的預設HTTPResponse
類現在支援緩衝,從而更快地讀取 HTTP 響應。(由 Kristján Valur Jónsson 貢獻;bpo-4879。)HTTPConnection
和HTTPSConnection
類現在支援 source_address 引數,這是一個(host, port)
2 元組,給出將用於連線的源地址。(由 Eldon Ziegler 貢獻;bpo-3972。)ihooks
模組現在支援相對匯入。請注意,ihooks
是一個較舊的用於自定義匯入的模組,已被 Python 2.0 中新增的imputil
模組取代。(相對匯入支援由 Neil Schemenauer 新增。)新函式:
inspect
模組的getcallargs()
接受一個可呼叫物件及其位置引數和關鍵字引數,並找出可呼叫物件的哪些引數將接收每個引數,返回一個將引數名對映到其值的字典。例如>>> from inspect import getcallargs >>> def f(a, b=1, *pos, **named): ... pass ... >>> getcallargs(f, 1, 2, 3) {'a': 1, 'b': 2, 'pos': (3,), 'named': {}} >>> getcallargs(f, a=2, x=4) {'a': 2, 'b': 1, 'pos': (), 'named': {'x': 4}} >>> getcallargs(f) Traceback (most recent call last): ... TypeError: f() takes at least 1 argument (0 given)
由 George Sakkis 貢獻;bpo-3135。
更新模組:
io
庫已升級到 Python 3.1 附帶的版本。對於 3.1,I/O 庫已完全用 C 重寫,根據執行的任務,速度提高了 2 到 20 倍。原始 Python 版本已重新命名為_pyio
模組。一個小的結果更改是:
io.TextIOBase
類現在有一個errors
屬性,用於給出編碼和解碼錯誤使用的錯誤設定('strict'
、'replace'
、'ignore'
之一)。io.FileIO
類在傳入無效檔案描述符時現在會引發OSError
。(由 Benjamin Peterson 實現;bpo-4991。)truncate()
方法現在保留檔案位置;以前它會將檔案位置更改為新檔案的末尾。(由 Pascal Chambon 修復;bpo-6939。)新函式:
itertools.compress(data, selectors)
接受兩個迭代器。如果 selectors 中的相應值為 true,則返回 data 的元素。itertools.compress('ABCDEF', [1,0,1,0,1,1]) => A, C, E, F
新函式:
itertools.combinations_with_replacement(iter, r)
返回來自可迭代物件 iter 的所有可能的 r 長度組合。與combinations()
不同,生成的組合中可以重複單個元素。itertools.combinations_with_replacement('abc', 2) => ('a', 'a'), ('a', 'b'), ('a', 'c'), ('b', 'b'), ('b', 'c'), ('c', 'c')
請注意,元素是否被視為唯一取決於它們在輸入中的位置,而不是它們的實際值。
itertools.count()
函式現在有一個 step 引數,允許以除 1 以外的值遞增。count()
現在也允許關鍵字引數,並使用非整數值,例如浮點數或Decimal
例項。(由 Raymond Hettinger 實現;bpo-5032。)itertools.combinations()
和itertools.product()
之前在 r 值大於輸入可迭代物件時會引發ValueError
。這被認為是一個規範錯誤,因此它們現在返回一個空迭代器。(由 Raymond Hettinger 修復;bpo-4816。)更新模組:
json
模組已升級到 simplejson 包的 2.0.9 版本,其中包括一個 C 擴充套件,可加快編碼和解碼速度。(由 Bob Ippolito 貢獻;bpo-4136。)為了支援新的
collections.OrderedDict
型別,json.load()
現在有一個可選的 object_pairs_hook 引數,它將在解碼為對列表的任何物件字面量時被呼叫。(由 Raymond Hettinger 貢獻;bpo-5381。)mailbox
模組的Maildir
類現在會記錄其讀取的目錄的時間戳,並且僅在修改時間隨後更改時才重新讀取它們。這透過避免不必要的目錄掃描來提高效能。(由 A.M. Kuchling 和 Antoine Pitrou 修復;bpo-1607951,bpo-6896。)新函式:
math
模組增加了erf()
和erfc()
用於誤差函式和互補誤差函式,expm1()
計算e**x - 1
,比使用exp()
減去 1 具有更高的精度,gamma()
用於 Gamma 函式,lgamma()
用於 Gamma 函式的自然對數。(由 Mark Dickinson 和 nirinA raseliarison 貢獻;bpo-3366。)multiprocessing
模組的Manager*
類現在可以傳入一個可呼叫物件,該物件將在每次啟動子程序時被呼叫,同時傳入一組將傳遞給該可呼叫物件的引數。(由 lekma 貢獻;bpo-5585。)Pool
類,它控制工作程序池,現在有一個可選的 maxtasksperchild 引數。工作程序將執行指定數量的任務,然後退出,導致Pool
啟動一個新的工作程序。這在任務可能洩漏記憶體或其他資源,或者某些任務會導致工作程序變得非常龐大時很有用。(由 Charles Cazabon 貢獻;bpo-6963。)nntplib
模組現在支援 IPv6 地址。(由 Derek Morr 貢獻;bpo-1664。)新函式:
os
模組封裝了以下 POSIX 系統呼叫:getresgid()
和getresuid()
,它們返回真實的、有效的和儲存的 GID 和 UID;setresgid()
和setresuid()
,它們將真實的、有效的和儲存的 GID 和 UID 設定為新值;initgroups()
,它初始化當前程序的組訪問列表。(GID/UID 函式由 Travis H. 貢獻;bpo-6508。對 initgroups 的支援由 Jean-Paul Calderone 新增;bpo-7333。)os.fork()
函式現在在子程序中重新初始化匯入鎖;這修復了在 Solaris 上從執行緒呼叫fork()
時出現的問題。(由 Zsolt Cserna 修復;bpo-7242。)在
os.path
模組中,normpath()
和abspath()
函式現在保留 Unicode;如果它們的輸入路徑是 Unicode 字串,則返回值也是 Unicode 字串。(normpath()
由 Matt Giuca 在 bpo-5827 中修復;abspath()
由 Ezio Melotti 在 bpo-3426 中修復。)pydoc
模組現在為 Python 使用的各種符號提供幫助。例如,您現在可以執行help('<<')
或help('@')
。(由 David Laban 貢獻;bpo-4739。)re
模組的split()
、sub()
和subn()
現在接受一個可選的 flags 引數,以與模組中的其他函式保持一致。(由 Gregory P. Smith 新增。)新函式:
run_path()
在runpy
模組中將執行提供的 path 引數的程式碼。path 可以是 Python 原始檔 (example.py
)、編譯的位元組碼檔案 (example.pyc
)、目錄 (./package/
) 或 zip 存檔 (example.zip
) 的路徑。如果提供了目錄或 zip 路徑,它將被新增到sys.path
的前面,並且模組__main__
將被匯入。預期目錄或 zip 包含__main__.py
;如果它不包含,則可能會從sys.path
中稍後的位置匯入其他__main__.py
。這使得runpy
的更多機制可供希望模擬 Python 命令列處理顯式路徑名方式的指令碼使用。(由 Nick Coghlan 新增;bpo-6816。)新函式:在
shutil
模組中,make_archive()
接受檔名、存檔型別(zip 或 tar 格式)和目錄路徑,並建立一個包含目錄內容的存檔。(由 Tarek Ziadé 新增。)shutil
的copyfile()
和copytree()
函式在被要求複製命名管道時現在會引發SpecialFileError
異常。以前,程式碼會將命名管道視為普通檔案,透過開啟它們進行讀取,這會無限期地阻塞。(由 Antoine Pitrou 修復;bpo-3002。)signal
模組不再重新安裝訊號處理程式,除非確實必要,這修復了一個可能導致無法可靠捕獲 EINTR 訊號的錯誤。(由 Charles-Francois Natali 修復;bpo-8354。)新函式:在
site
模組中,三個新函式返回各種站點和使用者特定的路徑。getsitepackages()
返回包含所有全域性 site-packages 目錄的列表,getusersitepackages()
返回使用者 site-packages 目錄的路徑,getuserbase()
返回USER_BASE
環境變數的值,給出可用於儲存資料的目錄路徑。(由 Tarek Ziadé 貢獻;bpo-6693。)site
模組現在會報告在匯入sitecustomize
模組時發生的異常,並且將不再捕獲和吞噬KeyboardInterrupt
異常。(由 Victor Stinner 修復;bpo-3137。)create_connection()
函式增加了一個 source_address 引數,這是一個(host, port)
2 元組,給出將用於連線的源地址。(由 Eldon Ziegler 貢獻;bpo-3972。)recv_into()
和recvfrom_into()
方法現在將寫入支援緩衝區 API 的物件,最有用的是bytearray
和memoryview
物件。(由 Antoine Pitrou 實現;bpo-8104。)SocketServer
模組的TCPServer
類現在支援套接字超時和停用 Nagle 演算法。disable_nagle_algorithm
類屬性預設為False
;如果被覆蓋為 true,則新的請求連線將設定 TCP_NODELAY 選項以防止將許多小的傳送緩衝到單個 TCP 資料包中。timeout
類屬性可以儲存一個以秒為單位的超時時間,該時間將應用於請求套接字;如果在該時間內未收到請求,則將呼叫handle_timeout()
,並且handle_request()
將返回。(由 Kristján Valur Jónsson 貢獻;bpo-6192 和 bpo-6267。)更新模組:
sqlite3
模組已更新到 pysqlite 包 的 2.6.0 版本。2.6.0 版本包含許多錯誤修復,並增加了從共享庫載入 SQLite 擴充套件的能力。呼叫enable_load_extension(True)
方法以啟用擴充套件,然後呼叫load_extension()
以載入特定的共享庫。(由 Gerhard Häring 更新。)ssl
模組的SSLSocket
物件現在支援緩衝區 API,這修復了測試套件失敗(由 Antoine Pitrou 修復;bpo-7133),並自動設定 OpenSSL 的SSL_MODE_AUTO_RETRY
,這將防止在觸發 SSL 重新協商的recv()
操作中返回錯誤程式碼(由 Antoine Pitrou 修復;bpo-8222)。wrap_socket()
建構函式現在接受一個 ciphers 引數,它是一個字串,列出了允許的加密演算法;字串的格式在 OpenSSL 文件中描述。(由 Antoine Pitrou 新增;bpo-8322。)另一個更改是擴充套件載入了所有 OpenSSL 的密碼和摘要演算法,以便它們都可用。一些 SSL 證書無法驗證,報告“未知演算法”錯誤。(由 Beda Kosata 報告,由 Antoine Pitrou 修復;bpo-8484。)
正在使用的 OpenSSL 版本現在作為模組屬性提供:
ssl.OPENSSL_VERSION
(一個字串),ssl.OPENSSL_VERSION_INFO
(一個 5 元組),以及ssl.OPENSSL_VERSION_NUMBER
(一個整數)。(由 Antoine Pitrou 新增;bpo-8321。)struct
模組在值對於特定整數格式程式碼(bBhHiIlLqQ
之一)過大時,將不再靜默忽略溢位錯誤;它現在總是引發struct.error
異常。(由 Mark Dickinson 更改;bpo-1523。)pack()
函式還將嘗試使用__index__()
轉換和打包非整數,然後嘗試__int__()
方法或報告錯誤。(由 Mark Dickinson 更改;bpo-8300。)新函式:
subprocess
模組的check_output()
執行帶有指定引數集的命令,並在命令執行時沒有錯誤時將其輸出作為字串返回,否則引發CalledProcessError
異常。>>> subprocess.check_output(['df', '-h', '.']) 'Filesystem Size Used Avail Capacity Mounted on\n /dev/disk0s2 52G 49G 3.0G 94% /\n' >>> subprocess.check_output(['df', '-h', '/bogus']) ... subprocess.CalledProcessError: Command '['df', '-h', '/bogus']' returned non-zero exit status 1
(由 Gregory P. Smith 貢獻。)
subprocess
模組現在在收到EINTR
訊號時將重試其內部系統呼叫。(由多人報告;最終補丁由 Gregory P. Smith 在 bpo-1068268 中提供。)新函式:
is_declared_global()
在symtable
模組中,對於明確宣告為全域性的變數返回 true,對於隱式全域性的變數返回 false。(由 Jeremy Hylton 貢獻。)syslog
模組現在將使用sys.argv[0]
的值作為識別符號,而不是以前的預設值'python'
。(由 Sean Reifschneider 更改;bpo-8451。)sys.version_info
值現在是一個命名元組,具有名為major
、minor
、micro
、releaselevel
和serial
的屬性。(由 Ross Light 貢獻;bpo-4285。)sys.getwindowsversion()
也返回一個命名元組,具有名為major
、minor
、build
、platform
、service_pack
、service_pack_major
、service_pack_minor
、suite_mask
和product_type
的屬性。(由 Brian Curtin 貢獻;bpo-7766。)tarfile
模組的預設錯誤處理已更改,不再抑制致命錯誤。預設錯誤級別以前是 0,這意味著錯誤只會導致訊息寫入除錯日誌,但由於除錯日誌預設未啟用,這些錯誤將不被注意。預設錯誤級別現在是 1,如果出現錯誤,則會引發異常。(由 Lars Gustäbel 更改;bpo-7357。)tarfile
現在支援過濾新增到 tar 檔案的TarInfo
物件。當您呼叫add()
時,您可以提供一個可選的 filter 引數,它是一個可呼叫物件。filter 可呼叫物件將傳入正在新增的每個檔案的TarInfo
,並可以修改並返回它。如果可呼叫物件返回None
,則該檔案將從結果存檔中排除。這比現有的 exclude 引數更強大,因此 exclude 已被棄用。(由 Lars Gustäbel 新增;bpo-6856。)TarFile
類現在也支援上下文管理協議。(由 Lars Gustäbel 新增;bpo-7232。)threading.Event
類的wait()
方法現在在退出時返回內部標誌。這意味著該方法通常會返回 true,因為wait()
應該阻塞直到內部標誌變為 true。返回值只有在提供了超時且操作超時時才會為 false。(由 Tim Lesher 貢獻;bpo-1674032。)unicodedata
模組提供的 Unicode 資料庫現在在內部用於確定哪些字元是數字、空白或表示換行符。該資料庫還包括來自Unihan.txt
資料檔案的資訊(由 Anders Chrigström 和 Amaury Forgeot d’Arc 提供補丁;bpo-1571184),並已更新到 5.2.0 版本(由 Florent Xicluna 更新;bpo-8024)。urlparse
模組的urlsplit()
現在以符合 RFC 3986 的方式處理未知 URL 方案:如果 URL 的形式為"<something>://..."
,則://
之前的文字被視為方案,即使它是一個模組不知道的虛構方案。此更改可能會破壞圍繞舊行為的程式碼。例如,Python 2.6.4 或 2.5 將返回以下內容>>> import urlparse >>> urlparse.urlsplit('invented://host/filename?query') ('invented', '', '//host/filename?query', '', '')
Python 2.7 (和 Python 2.6.5) 將返回
>>> import urlparse >>> urlparse.urlsplit('invented://host/filename?query') ('invented', 'host', '/filename?query', '', '')
(Python 2.7 實際上會產生略有不同的輸出,因為它返回一個命名元組而不是標準元組。)
urlparse
模組還支援 RFC 2732 定義的 IPv6 字面量地址(由 Senthil Kumaran 貢獻;bpo-2987)。>>> urlparse.urlparse('http://[1080::8:800:200C:417A]/foo') ParseResult(scheme='http', netloc='[1080::8:800:200C:417A]', path='/foo', params='', query='', fragment='')
新類:
WeakSet
類在weakref
模組中是一個只持有對其元素弱引用的集合;一旦沒有引用指向它們,元素將被移除。(最初由 Raymond Hettinger 在 Python 3.x 中實現,並由 Michael Foord 反向移植到 2.7。)xml.etree.ElementTree
庫在輸出 XML 處理指令(看起來像<?xml-stylesheet href="#style1"?>
)或註釋(看起來像<!-- comment -->
)時,不再轉義 & 符號和尖括號。(由 Neil Muller 提供補丁;bpo-2746。)XML-RPC 客戶端和伺服器,由
xmlrpclib
和SimpleXMLRPCServer
模組提供,透過支援 HTTP/1.1 持久連線和可選地使用 gzip 編碼壓縮交換的 XML,提高了效能。gzip 壓縮由SimpleXMLRPCRequestHandler
的encode_threshold
屬性控制,該屬性包含一個以位元組為單位的大小;大於此大小的響應將被壓縮。(由 Kristján Valur Jónsson 貢獻;bpo-6267。)zipfile
模組的ZipFile
現在支援上下文管理協議,因此您可以編寫with zipfile.ZipFile(...) as f:
。(由 Brian Curtin 貢獻;bpo-5511。)zipfile
現在也支援歸檔空目錄並正確提取它們。(由 Kuba Wieczorek 修復;bpo-4710。) 從歸檔中讀取檔案更快,並且交錯的read()
和readline()
現在可以正常工作。(由 Nir Aides 貢獻;bpo-7610。)is_zipfile()
函式現在除了早期版本接受的路徑名之外,還接受檔案物件。(由 Gabriel Genellina 貢獻;bpo-4756。)writestr()
方法現在有一個可選的 compress_type 引數,允許您覆蓋在ZipFile
建構函式中指定的預設壓縮方法。(由 Ronald Oussoren 貢獻;bpo-6003。)
新模組:importlib¶
Python 3.1 包含 importlib
包,它是 Python import
語句底層邏輯的重新實現。importlib
對於 Python 直譯器的實現者以及希望編寫可以參與匯入過程的新匯入器的使用者很有用。Python 2.7 不包含完整的 importlib
包,而是包含一個微小的子集,其中包含一個函式 import_module()
。
import_module(name, package=None)
匯入一個模組。name 是包含模組或包名稱的字串。透過提供以 .
字元開頭的字串,例如 ..utils.errors
,可以進行相對匯入。對於相對匯入,必須提供 package 引數,它將用作相對匯入的錨點的包名稱。import_module()
既將匯入的模組插入 sys.modules
,也返回模組物件。
以下是一些示例:
>>> from importlib import import_module
>>> anydbm = import_module('anydbm') # Standard absolute import
>>> anydbm
<module 'anydbm' from '/p/python/Lib/anydbm.py'>
>>> # Relative import
>>> file_util = import_module('..file_util', 'distutils.command')
>>> file_util
<module 'distutils.file_util' from '/python/Lib/distutils/file_util.pyc'>
importlib
由 Brett Cannon 實現,並在 Python 3.1 中引入。
新模組:sysconfig¶
sysconfig
模組已從 Distutils 包中剝離出來,成為一個新的頂級模組。sysconfig
提供了獲取 Python 構建過程資訊的函式:編譯器開關、安裝路徑、平臺名稱以及 Python 是否從其源目錄執行。
模組中的一些函式是:
get_config_var()
返回 Python 的 Makefile 和pyconfig.h
檔案中的變數。get_config_vars()
返回一個包含所有配置變數的字典。get_path()
返回特定型別模組的配置路徑:標準庫、站點特定模組、平臺特定模組等。is_python_build()
如果您正在執行 Python 源樹中的二進位制檔案,則返回 true,否則返回 false。
請查閱 sysconfig
文件以獲取更多詳細資訊和完整的函式列表。
Distutils 包和 sysconfig
現在由 Tarek Ziadé 維護,他還啟動了一個 Distutils2 包(原始碼倉庫在 https://hg.python.org/distutils2/),用於開發下一代 Distutils。
ttk: Tk 的主題化小部件¶
Tcl/Tk 8.5 包含一套主題化小部件,它們重新實現了基本的 Tk 小部件,但具有更可定製的外觀,因此可以更接近本機平臺的小部件。這套小部件最初被稱為 Tile,但在新增到 Tcl/Tck 8.5 版本時更名為 Ttk(“themed Tk”的縮寫)。
要了解更多資訊,請閱讀 ttk
模組文件。您可能還希望閱讀 Tcl/Tk 手冊頁中描述 Ttk 主題引擎的部分,可在 https://www.tcl.tk/man/tcl8.5/TkCmd/ttk_intro.html 獲取。一些正在使用的 Python/Ttk 程式碼截圖可在 https://code.google.com/archive/p/python-ttk/wikis/Screenshots.wiki 獲取。
tkinter.ttk
模組由 Guilherme Polo 編寫,並新增到 bpo-2983。一個名為 Tile.py
的替代版本,由 Martin Franklin 編寫並由 Kevin Walzer 維護,曾提議包含在 bpo-2618 中,但作者認為 Guilherme Polo 的工作更全面。
更新模組:unittest¶
unittest
模組得到了極大的增強;添加了許多新功能。除非另有說明,這些功能大部分由 Michael Foord 實現。增強版的模組可以單獨下載,用於 Python 2.4 到 2.6 版本,打包為 unittest2
包,可在 unittest2 獲取。
從命令列使用時,該模組可以自動發現測試。它不如 py.test 或 nose 那麼花哨,但提供了一種執行儲存在一組包目錄中的測試的簡單方法。例如,以下命令將搜尋 test/
子目錄中名為 test*.py
的任何可匯入測試檔案
python -m unittest discover -s test
請查閱 unittest
模組文件以獲取更多詳細資訊。(在 bpo-6001 中開發。)
main()
函式支援其他一些新選項
-b
或--buffer
將在每個測試期間緩衝標準輸出和標準錯誤流。如果測試透過,任何產生的輸出都將被丟棄;如果失敗,則顯示緩衝的輸出。-c
或--catch
將使 Ctrl-C 中斷處理得更優雅。它不會立即中斷測試過程,而是會完成當前正在執行的測試,然後報告中斷前的部分結果。如果您不耐煩,第二次按下 Ctrl-C 將導致立即中斷。這個 Ctrl-C 處理器透過注意訊號處理器是否已設定並呼叫它來避免在被測試的程式碼或正在執行的測試已定義自己的訊號處理器時引起問題。如果這對您不起作用,有一個
removeHandler()
裝飾器可用於標記應停用 Ctrl-C 處理的測試。-f
或--failfast
使測試在失敗時立即停止執行,而不是繼續執行後續測試。(由 Cliff Dyer 建議,由 Michael Foord 實現;bpo-8074。)
在詳細模式下執行時,進度訊息現在顯示“x”表示預期失敗,“u”表示意外成功。(由 Benjamin Peterson 貢獻。)
測試用例可以引發 SkipTest
異常以跳過測試 (bpo-1034053)。
assertEqual()
、assertTrue()
和 assertFalse()
失敗的錯誤訊息現在提供更多資訊。如果將 longMessage
屬性設定為 true,則會列印標準錯誤訊息以及您提供的任何附加訊息。(由 Michael Foord 新增;bpo-5663。)
在不提供可呼叫物件來執行的情況下呼叫 assertRaises()
方法時,它現在返回一個上下文處理程式。例如,您可以這樣寫:
with self.assertRaises(KeyError):
{}['foo']
(由 Antoine Pitrou 實現;bpo-4444。)
現在支援模組級和類級的設定和拆卸裝置。模組可以包含 setUpModule()
和 tearDownModule()
函式。類可以有 setUpClass()
和 tearDownClass()
方法,這些方法必須定義為類方法(使用 @classmethod
或等效)。當測試執行器切換到不同模組或類中的測試用例時,會呼叫這些函式和方法。
添加了 addCleanup()
和 doCleanups()
方法。addCleanup()
允許您新增無條件呼叫的清理函式(如果 setUp()
失敗,則在 setUp()
之後;否則在 tearDown()
之後)。這使得測試期間的資源分配和釋放更加簡單 (bpo-5679)。
添加了許多新方法,提供更專業的測試。其中許多方法由 Google 工程師編寫,用於他們的測試套件;Gregory P. Smith、Michael Foord 和 GvR 致力於將它們合併到 Python 的 unittest
版本中。
assertIsNone()
和assertIsNotNone()
接受一個表示式,並驗證結果是否為None
。assertIs()
和assertIsNot()
接受兩個值,並檢查這兩個值是否求值為同一個物件。(由 Michael Foord 新增;bpo-2578。)assertIsInstance()
和assertNotIsInstance()
檢查結果物件是否是特定類或類元組的例項。(由 Georg Brandl 新增;bpo-7031。)assertGreater()
、assertGreaterEqual()
、assertLess()
和assertLessEqual()
比較兩個量。assertMultiLineEqual()
比較兩個字串,如果不相等,則顯示有用的比較,突出顯示兩個字串中的差異。現在,當 Unicode 字串與assertEqual()
比較時,預設使用此比較。assertRegexpMatches()
和assertNotRegexpMatches()
檢查第一個引數是否是與作為第二個引數提供的正則表示式匹配或不匹配的字串 (bpo-8038)。assertRaisesRegexp()
檢查是否引發了特定異常,然後還檢查異常的字串表示是否與提供的正則表示式匹配。assertIn()
和assertNotIn()
測試 first 是否在 second 中。assertItemsEqual()
測試兩個提供的序列是否包含相同的元素。assertSetEqual()
比較兩個集合是否相等,如果出現錯誤,則只報告集合之間的差異。類似地,
assertListEqual()
和assertTupleEqual()
比較指定的型別並解釋任何差異,而不一定列印它們的完整值;現在,當使用assertEqual()
比較列表和元組時,預設使用這些方法。更一般地,assertSequenceEqual()
比較兩個序列,並可選擇檢查兩個序列是否為特定型別。assertDictEqual()
比較兩個字典並報告差異;現在,當您使用assertEqual()
比較兩個字典時,預設使用它。assertDictContainsSubset()
檢查 first 中的所有鍵/值對是否在 second 中找到。assertAlmostEqual()
和assertNotAlmostEqual()
測試 first 和 second 是否近似相等。此方法可以將其差異四捨五入到可選指定的 places 數(預設為 7)並與零進行比較,或者要求差異小於提供的 delta 值。loadTestsFromName()
正確遵守suiteClass
屬性。(由 Mark Roddy 修復;bpo-6866。)一個新鉤子允許您擴充套件
assertEqual()
方法以處理新的資料型別。addTypeEqualityFunc()
方法接受一個型別物件和一個函式。當比較的兩個物件都屬於指定型別時,將使用該函式。該函式應比較兩個物件並在它們不匹配時引發異常;最好該函式提供有關兩個物件不匹配原因的附加資訊,就像新的序列比較方法一樣。
unittest.main()
現在接受一個可選的 exit
引數。如果為 false,則 main()
不呼叫 sys.exit()
,從而允許從互動式直譯器使用 main()
。(由 J. Pablo Fernández 貢獻;bpo-3379。)
TestResult
有新的 startTestRun()
和 stopTestRun()
方法,它們在測試執行之前和之後立即呼叫。(由 Robert Collins 貢獻;bpo-5728。)
由於所有這些變化,unittest.py
變得過於龐大,因此該模組被轉換為一個包,程式碼被拆分為多個檔案(由 Benjamin Peterson 完成)。這不影響模組的匯入或使用方式。
參見
- https://web.archive.org/web/20210619163128/http://www.voidspace.org.uk/python/articles/unittest2.shtml
描述了新功能、如何使用它們以及各種設計決策的理由。(由 Michael Foord 完成。)
更新模組:ElementTree 1.3¶
Python 中包含的 ElementTree 庫版本已更新到 1.3 版。一些新功能包括:
各種解析函式現在接受一個 parser 關鍵字引數,提供將使用的
XMLParser
例項。這使得覆蓋檔案的內部編碼成為可能p = ET.XMLParser(encoding='utf-8') t = ET.XML("""<root/>""", parser=p)
解析 XML 中的錯誤現在會引發
ParseError
異常,其例項具有position
屬性,其中包含一個 (line, column) 元組,給出問題的位置。ElementTree 將樹轉換為字串的程式碼已進行了顯著的重寫,在許多情況下使其速度大約提高了一倍。
ElementTree.write()
和Element.write()
方法現在有一個 method 引數,可以是“xml”(預設)、“html”或“text”。HTML 模式將空元素輸出為<empty></empty>
而不是<empty/>
,文字模式將跳過元素並只輸出文本塊。如果將元素的tag
屬性設定為None
但保留其子元素,則在寫入樹時將省略該元素,因此無需進行更廣泛的重新排列來刪除單個元素。名稱空間處理也得到了改進。所有
xmlns:<whatever>
宣告現在都在根元素上輸出,而不是散佈在生成的 XML 中。您可以透過設定default_namespace
屬性來設定樹的預設名稱空間,並可以使用register_namespace()
註冊新字首。在 XML 模式下,您可以使用 true/false xml_declaration 引數來抑制 XML 宣告。新的
Element
方法:extend()
將序列中的專案附加到元素的子元素。元素本身的行為類似於序列,因此很容易將子元素從一個元素移動到另一個元素from xml.etree import ElementTree as ET t = ET.XML("""<list> <item>1</item> <item>2</item> <item>3</item> </list>""") new = ET.XML('<root/>') new.extend(t) # Outputs <root><item>1</item>...</root> print ET.tostring(new)
新的
Element
方法:iter()
以生成器形式生成元素的子元素。也可以編寫for child in elem:
來遍歷元素的子元素。現有的方法getiterator()
現已棄用,getchildren()
也已棄用,它構造並返回一個子元素列表。新的
Element
方法:itertext()
生成元素的所有後代文字塊。例如:t = ET.XML("""<list> <item>1</item> <item>2</item> <item>3</item> </list>""") # Outputs ['\n ', '1', ' ', '2', ' ', '3', '\n'] print list(t.itertext())
已棄用:將元素用作布林值(即
if elem:
)如果元素有任何子元素則返回 true,如果沒有子元素則返回 false。這種行為令人困惑——None
是 false,但沒有子元素的元素也是 false?——所以現在它將觸發FutureWarning
。在您的程式碼中,您應該明確:如果您對子元素的數量感興趣,請編寫len(elem) != 0
,或者elem is not None
。
Fredrik Lundh 開發了 ElementTree 併發布了 1.3 版本;您可以在 https://web.archive.org/web/20200703234532/http://effbot.org/zone/elementtree-13-intro.htm 閱讀他描述 1.3 的文章。Florent Xicluna 在 python-dev 和 bpo-6472 討論後更新了 Python 中包含的版本。)
構建和 C API 更改¶
Python 的構建過程和 C API 的更改包括
最新發布的 GNU 偵錯程式 GDB 7 可以使用 Python 編寫指令碼。當您開始除錯可執行程式 P 時,GDB 將查詢名為
P-gdb.py
的檔案並自動讀取它。Dave Malcolm 貢獻了一個python-gdb.py
,它添加了許多在除錯 Python 本身時有用的命令。例如,py-up
和py-down
上下移動一個 Python 堆疊幀,這通常對應於幾個 C 堆疊幀。py-print
列印 Python 變數的值,py-bt
列印 Python 堆疊跟蹤。(由於 bpo-8032 而新增。)如果您使用 Python 提供的
.gdbinit
檔案,2.7 版本中的“pyo”宏現在在除錯執行緒不持有 GIL 時也能正常工作;該宏現在在列印之前獲取 GIL。(由 Victor Stinner 貢獻;bpo-3632。)Py_AddPendingCall()
現在是執行緒安全的,允許任何工作執行緒向主 Python 執行緒提交通知。這對於非同步 IO 操作特別有用。(由 Kristján Valur Jónsson 貢獻;bpo-4293。)新函式:
PyCode_NewEmpty()
建立一個空的位元組碼物件;只需要檔名、函式名和第一行號。這對於嘗試構造更有用回溯堆疊的擴充套件模組很有用。以前,此類擴充套件需要呼叫PyCode_New()
,後者有更多引數。(由 Jeffrey Yasskin 新增。)新函式:
PyErr_NewExceptionWithDoc()
建立一個新的異常類,就像現有的PyErr_NewException()
所做的那樣,但接受一個額外的char *
引數,其中包含新異常類的文件字串。(由 Python bug 跟蹤器上的“lekma”新增;bpo-7033。)新函式:
PyFrame_GetLineNumber()
接受一個幀物件並返回該幀當前正在執行的行號。以前,程式碼需要獲取當前執行的位元組碼指令的索引,然後查詢與該地址對應的行號。(由 Jeffrey Yasskin 新增。)新函式:
PyLong_AsLongAndOverflow()
和PyLong_AsLongLongAndOverflow()
將 Python 長整數近似為 C long 或 long long。如果數字太大而無法容納到輸出型別中,則會設定一個 overflow 標誌並返回給呼叫者。(由 Case Van Horsen 貢獻;bpo-7528 和 bpo-7767。)新函式:源於字串到浮點數轉換的重寫,添加了一個新的
PyOS_string_to_double()
函式。舊的PyOS_ascii_strtod()
和PyOS_ascii_atof()
函式現已棄用。新函式:
PySys_SetArgvEx()
設定sys.argv
的值,並可選擇根據 updatepath 引數的值更新sys.path
以包含由sys.argv[0]
命名的指令碼所在的目錄。新增此函式是為了彌補嵌入 Python 的應用程式中的一個安全漏洞。舊函式
PySys_SetArgv()
總是會更新sys.path
,有時還會添加當前目錄。這意味著,如果您在由其他人控制的目錄中執行嵌入 Python 的應用程式,攻擊者可能會在該目錄中放置一個特洛伊木馬模組(例如,一個名為os.py
的檔案),您的應用程式將匯入並執行它。如果您維護嵌入 Python 的 C/C++ 應用程式,請檢查您是否正在呼叫
PySys_SetArgv()
,並仔細考慮應用程式是否應使用 updatepath 設定為 false 的PySys_SetArgvEx()
。安全問題報告為 CVE 2008-5983;在 bpo-5753 中討論,由 Antoine Pitrou 修復。
新宏:Python 標頭檔案現在定義了以下宏:
Py_ISALNUM
、Py_ISALPHA
、Py_ISDIGIT
、Py_ISLOWER
、Py_ISSPACE
、Py_ISUPPER
、Py_ISXDIGIT
、Py_TOLOWER
和Py_TOUPPER
。所有這些函式都類似於 C 標準中用於字元分類的宏,但忽略當前的區域設定,因為在某些地方 Python 需要以獨立於區域設定的方式分析字元。(由 Eric Smith 新增;bpo-5793。)已刪除函式:
PyEval_CallObject()
現在只作為宏可用。以前保留一個函式版本是為了保持 ABI 連結相容性,但這發生在 1997 年;現在肯定可以刪除了。(由 Antoine Pitrou 刪除;bpo-8276。)新格式程式碼:
PyString_FromFormat()
、PyString_FromFormatV()
和PyErr_Format()
函式現在接受%lld
和%llu
格式程式碼,用於顯示 C 的 long long 型別。(由 Mark Dickinson 貢獻;bpo-7228。)執行緒和程序分叉之間的複雜互動已更改。以前,由
os.fork()
建立的子程序可能會失敗,因為子程序只執行一個執行緒,即執行os.fork()
的執行緒。如果在執行分叉時其他執行緒持有鎖,例如 Python 的匯入鎖,則在新程序中該鎖仍將被標記為“持有”。但在子程序中,由於其他執行緒未複製,因此永遠不會釋放該鎖,並且子程序將無法再執行匯入。Python 2.7 在執行
os.fork()
之前獲取匯入鎖,並且還將清理使用threading
模組建立的任何鎖。具有內部鎖或自行呼叫fork()
的 C 擴充套件模組不會從這種清理中受益。(由 Thomas Wouters 修復;bpo-1590864。)
Py_Finalize()
函式現在呼叫內部threading._shutdown()
函式;這可以防止在直譯器關閉時引發一些異常。(由 Adam Olsen 修補;bpo-1722344。)當使用
PyMemberDef
結構定義型別的屬性時,Python 將不再允許您嘗試刪除或設定T_STRING_INPLACE
屬性。ctypes
模組定義的全域性符號現在以Py
或_ctypes
為字首。(由 Thomas Heller 實現;bpo-3102。)新的配置選項:
--with-system-expat
開關允許使用系統 Expat 庫構建pyexpat
模組。(由 Arfrever Frehtes Taifersar Arahesis 貢獻;bpo-7609。)新配置選項:
--with-valgrind
選項現在將停用 pymalloc 分配器,Valgrind 記憶體錯誤檢測器很難正確分析它。因此,Valgrind 將更好地檢測記憶體洩漏和溢位。(由 James Henstridge 貢獻;bpo-2422。)新的配置選項:現在可以為
--with-dbmliborder=
提供一個空字串,以停用所有各種 DBM 模組。(由 Arfrever Frehtes Taifersar Arahesis 新增;bpo-6491。)configure 指令碼現在檢查某些 32 位 Intel 晶片上的浮點舍入錯誤,並定義
X87_DOUBLE_ROUNDING
預處理器定義。目前沒有程式碼使用此定義,但如果有人希望使用,它是可用的。(由 Mark Dickinson 新增;bpo-2937。)configure 現在還為支援 C++ 連結設定了
LDCXXSHARED
Makefile 變數。(由 Arfrever Frehtes Taifersar Arahesis 貢獻;bpo-1222585。)構建過程現在為 pkg-config 支援建立必要的檔案。(由 Clinton Roy 貢獻;bpo-3585。)
構建過程現在支援 Subversion 1.7。(由 Arfrever Frehtes Taifersar Arahesis 貢獻;bpo-6094。)
膠囊 (Capsules)¶
Python 3.1 添加了一種新的 C 資料型別 PyCapsule
,用於為擴充套件模組提供 C API。膠囊本質上是 C void *
指標的持有者,並作為模組屬性提供;例如,socket
模組的 API 公開為 socket.CAPI
,而 unicodedata
公開 ucnhash_CAPI
。其他擴充套件可以匯入模組,訪問其字典以獲取膠囊物件,然後獲取 void *
指標,該指標通常指向模組各種 API 函式的指標陣列。
目前已有一個用於此目的的資料型別 PyCObject
,但它不提供型別安全。用純 Python 編寫的惡意程式碼可能會透過從模組 A 中獲取一個 PyCObject
並以某種方式將其替換為模組 B 中的 PyCObject
來導致段錯誤。膠囊知道它們自己的名稱,並且獲取指標需要提供名稱
void *vtable;
if (!PyCapsule_IsValid(capsule, "mymodule.CAPI") {
PyErr_SetString(PyExc_ValueError, "argument type invalid");
return NULL;
}
vtable = PyCapsule_GetPointer(capsule, "mymodule.CAPI");
您可以確保 vtable
指向您期望的任何內容。如果傳入了不同的膠囊,PyCapsule_IsValid()
將檢測到不匹配的名稱並返回 false。有關使用這些物件的更多資訊,請參閱 為擴充套件模組提供 C API。
Python 2.7 現在內部使用膠囊來提供各種擴充套件模組 API,但 PyCObject_AsVoidPtr()
已修改為處理膠囊,從而保持與 PyCObject
介面的編譯時相容性。使用 PyCObject_AsVoidPtr()
將發出 PendingDeprecationWarning
,預設情況下它是無聲的。
在 Python 3.1 中實現並由 Larry Hastings 反向移植到 2.7;在 bpo-5630 中討論。
特定於埠的更改:Windows¶
msvcrt
模組現在包含crtassem.h
標頭檔案中的一些常量:CRT_ASSEMBLY_VERSION
、VC_ASSEMBLY_PUBLICKEYTOKEN
和LIBRARIES_ASSEMBLY_NAME_PREFIX
。(由 David Cournapeau 貢獻;bpo-4365。)用於訪問登錄檔的
_winreg
模組現在實現了CreateKeyEx()
和DeleteKeyEx()
函式,它們是以前支援的函式的擴充套件版本,接受幾個額外的引數。DisableReflectionKey()
、EnableReflectionKey()
和QueryReflectionKey()
也經過測試並記錄。(由 Brian Curtin 實現:bpo-7347。)新的
_beginthreadex()
API 用於啟動執行緒,並且現在使用本機執行緒本地儲存功能。(由 Kristján Valur Jónsson 貢獻;bpo-3582。)os.kill()
函式現在在 Windows 上工作。訊號值可以是常量CTRL_C_EVENT
、CTRL_BREAK_EVENT
或任何整數。前兩個常量將向子程序傳送 Control-C 和 Control-Break 鍵盤事件;任何其他值將使用TerminateProcess()
API。(由 Miki Tebeka 貢獻;bpo-1220212。)os.listdir()
函式現在對空路徑正確失敗。(由 Hirokazu Yamamoto 修復;bpo-5913。)mimetypes
模組現在將在初始化時從 Windows 登錄檔讀取 MIME 資料庫。(由 Gabriel Genellina 修補;bpo-4969。)
特定於埠的更改:Mac OS X¶
路徑
/Library/Python/2.7/site-packages
現在被附加到sys.path
,以便在系統安裝和使用者安裝的相同版本之間共享新增的包。(由 Ronald Oussoren 更改;bpo-4865。)版本 2.7.13 中的更改:自 2.7.13 起,此更改已被移除。
/Library/Python/2.7/site-packages
,Apple 提供的系統 Python 2.7 使用的 site-packages 目錄,不再附加到使用者安裝的 Python(例如來自 python.org 安裝程式)的sys.path
。自 macOS 10.12 起,Apple 更改了系統 site-packages 目錄的配置方式,這可能導致 pip 元件(如 setuptools)的安裝失敗。為系統 Python 安裝的包將不再與使用者安裝的 Python 共享。( bpo-28440 )
特定於埠的更改:FreeBSD¶
FreeBSD 7.1 的
SO_SETFIB
常量,與socket()
方法getsockopt()
/setsockopt()
一起用於選擇備用路由表,現在可在socket
模組中使用。(由 Kyle VanderBeek 新增;bpo-8235。)
其他更改和修復¶
兩個基準測試指令碼
iobench
和ccbench
已新增到Tools
目錄。iobench
測量open()
返回的內建檔案 I/O 物件在執行各種操作時的速度,ccbench
是一個併發基準測試,它嘗試測量在使用不同數量的執行緒執行多個任務時的計算吞吐量、執行緒切換延遲和 IO 處理頻寬。Tools/i18n/msgfmt.py
指令碼現在支援.po
檔案中的複數形式。(由 Martin von Löwis 修復;bpo-5464。)從具有現有
.py
對應檔案的.pyc
或.pyo
檔案匯入模組時,如果原始檔名已過時,則生成的程式碼物件的co_filename
屬性將被覆蓋。這可能發生在檔案已重新命名、移動或透過不同路徑訪問時。(由 Ziga Seilnacht 和 Jean-Paul Calderone 修補;bpo-1180193。)regrtest.py
指令碼現在接受一個--randseed=
開關,它接受一個整數,該整數將用作以隨機順序執行測試的-r
選項的隨機種子。-r
選項還會報告所使用的種子。(由 Collin Winter 新增。)另一個
regrtest.py
開關是-j
,它接受一個整數,指定並行執行多少個測試。這可以減少多核機器上的總執行時間。此選項相容其他幾個選項,包括已知會產生較長執行時間的-R
開關。(由 Antoine Pitrou 新增,bpo-6152。) 這也可以與新的-F
開關一起使用,後者以迴圈方式執行選定的測試直到它們失敗。(由 Antoine Pitrou 新增;bpo-7312。)當作為指令碼執行時,
py_compile.py
模組現在接受'-'
作為引數,它將從標準輸入讀取要編譯的檔名列表。(由 Piotr Ożarowski 貢獻;bpo-8233。)
移植到 Python 2.7¶
本節列出以前描述的更改以及可能需要更改您的程式碼的其他錯誤修復
range()
函式更一致地處理其引數;現在它將對提供給它的非浮點、非整數引數呼叫__int__()
。(由 Alexander Belopolsky 修復;bpo-1533。)字串
format()
方法將浮點數和複數的預設精度從 6 位小數更改為 12 位,這與str()
使用的精度匹配。(由 Eric Smith 更改;bpo-5920。)由於
with
語句的最佳化,特殊方法__enter__()
和__exit__()
必須屬於物件的型別,不能直接附加到物件的例項。這影響新式類(派生自object
)和 C 擴充套件型別。( bpo-6101 )。由於 Python 2.6 中的一個錯誤,
__exit__()
方法的 exc_value 引數通常是異常的字串表示,而不是例項。這在 2.7 中已修復,因此 exc_value 將按預期是例項。(由 Florent Xicluna 修復;bpo-7853。)當使用
__slots__
設定了一組受限的屬性時,刪除未設定的屬性不會像您預期那樣引發AttributeError
。Benjamin Peterson 修復了此問題;bpo-7604。)
在標準庫中
使用
datetime
例項導致年份超出支援範圍的操作並不總是引發OverflowError
。現在更仔細地檢查這些錯誤,並將引發異常。(由 Mark Leander 報告,由 Anand B. Pillai 和 Alexander Belopolsky 修補;bpo-7150。)當使用
Decimal
例項和字串的format()
方法時,預設對齊方式以前是左對齊。這已更改為右對齊,這可能會改變您程式的輸出。(由 Mark Dickinson 更改;bpo-6857。)涉及信令 NaN 值(或
sNAN
)的比較現在會發出InvalidOperation
訊號,而不是根據比較運算子靜默返回 true 或 false 值。靜默 NaN 值(或NaN
)現在是可雜湊的。(由 Mark Dickinson 修復;bpo-7279。)xml.etree.ElementTree
庫在輸出 XML 處理指令(看起來像<?xml-stylesheet href="#style1"?>
)或註釋(看起來像<!-- comment -->
)時不再轉義 & 符號和尖括號。(由 Neil Muller 修補;bpo-2746。)StringIO
物件的readline()
方法在請求負長度時現在什麼也不做,就像其他類檔案物件一樣。( bpo-7348 )。syslog
模組現在將使用sys.argv[0]
的值作為識別符號,而不是以前的預設值'python'
。(由 Sean Reifschneider 更改;bpo-8451。)tarfile
模組的預設錯誤處理已更改,不再抑制致命錯誤。預設錯誤級別以前是 0,這意味著錯誤只會導致訊息寫入除錯日誌,但由於除錯日誌預設未啟用,這些錯誤將不被注意。預設錯誤級別現在是 1,如果出現錯誤,則會引發異常。(由 Lars Gustäbel 更改;bpo-7357。)urlparse
模組的urlsplit()
現在以符合 RFC 3986 的方式處理未知 URL 方案:如果 URL 的形式為"<something>://..."
,則://
之前的文字被視為方案,即使它是一個模組不知道的虛構方案。此更改可能會破壞圍繞舊行為工作的程式碼。例如,Python 2.6.4 或 2.5 將返回以下內容>>> import urlparse >>> urlparse.urlsplit('invented://host/filename?query') ('invented', '', '//host/filename?query', '', '')
Python 2.7 (和 Python 2.6.5) 將返回
>>> import urlparse >>> urlparse.urlsplit('invented://host/filename?query') ('invented', 'host', '/filename?query', '', '')
(Python 2.7 實際上會產生略有不同的輸出,因為它返回一個命名元組而不是標準元組。)
對於 C 擴充套件
使用整數格式程式碼和
PyArg_Parse*
系列函式的 C 擴充套件現在將引發TypeError
異常,而不是觸發DeprecationWarning
(bpo-5080)。使用新的
PyOS_string_to_double()
函式代替舊的PyOS_ascii_strtod()
和PyOS_ascii_atof()
函式,它們現已棄用。
對於嵌入 Python 的應用程式
添加了
PySys_SetArgvEx()
函式,允許應用程式在使用現有PySys_SetArgv()
函式時修復安全漏洞。檢查您是否正在呼叫PySys_SetArgv()
,並仔細考慮應用程式是否應使用 updatepath 設定為 false 的PySys_SetArgvEx()
。
新增到 Python 2.7 維護版本的新功能¶
當情況確實需要時,Python 2.7 維護版本中可能會新增新功能。任何此類新增都必須透過 Python 增強提案流程,並提供令人信服的理由,說明為什麼它們無法透過僅將新功能新增到 Python 3 或將其釋出到 Python 包索引來充分解決。
除了下面列出的具體提案外,還有一個通用豁免,允許在任何 Python 2.7 維護版本中新增新的 -3
警告。
除錯模式的兩個新環境變數¶
在除錯模式下,[xxx refs]
統計資訊預設不寫入,現在還必須設定 PYTHONSHOWREFCOUNT
環境變數。(由 Victor Stinner 貢獻;bpo-31733。)
當 Python 用 COUNT_ALLOC
編譯時,分配計數預設不再轉儲:現在還必須設定 PYTHONSHOWALLOCCOUNT
環境變數。此外,分配計數現在轉儲到 stderr,而不是 stdout。(由 Victor Stinner 貢獻;bpo-31692。)
在 2.7.15 版本中新增。
PEP 434: IDLE 增強功能所有分支例外¶
PEP 434 描述了對與 Python 一起釋出的 IDLE 開發環境所做更改的通用豁免。此豁免使 IDLE 開發人員能夠在所有受支援的 Python 2 和 3 版本中提供更一致的使用者體驗。
有關任何 IDLE 更改的詳細資訊,請參閱特定版本的 NEWS 檔案。
PEP 466: Python 2.7 的網路安全增強功能¶
PEP 466 描述了一些網路安全增強提案,這些提案已獲准包含在 Python 2.7 維護版本中,其中第一個更改出現在 Python 2.7.7 版本中。
PEP 466 相關功能已在 Python 2.7.7 中新增
hmac.compare_digest()
從 Python 3 反向移植,為 Python 2 應用程式提供抵抗時序攻擊的比較操作。(由 Alex Gaynor 貢獻;bpo-21306。)OpenSSL 1.0.1g 已在 python.org 上釋出的官方 Windows 安裝程式中升級。(由 Zachary Ware 貢獻;bpo-21462。)
PEP 466 相關功能已在 Python 2.7.8 中新增
hashlib.pbkdf2_hmac()
從 Python 3 反向移植,為 Python 2 應用程式廣泛提供適用於安全密碼儲存的雜湊演算法。(由 Alex Gaynor 貢獻;bpo-21304。)OpenSSL 1.0.1h 已為 python.org 上釋出的官方 Windows 安裝程序升級。(由 Zachary Ware 在 bpo-21671 中為 CVE 2014-0224 貢獻。)
PEP 466 相關功能已在 Python 2.7.9 中新增
Python 3.4 的
ssl
模組的大部分已反向移植。這意味著ssl
現在支援伺服器名稱指示、TLS1.x 設定、訪問平臺證書儲存、SSLContext
類以及其他功能。(由 Alex Gaynor 和 David Reid 貢獻;bpo-21308。)有關具體細節,請參閱模組文件中的“版本新增:2.7.9”註釋。
os.urandom()
已更改為快取指向/dev/urandom
的檔案描述符,而不是每次呼叫時都重新開啟/dev/urandom
。(由 Alex Gaynor 貢獻;bpo-21305。)hashlib.algorithms_guaranteed
和hashlib.algorithms_available
從 Python 3 反向移植,以便 Python 2 應用程式更容易選擇最強的可用雜湊演算法。(由 Alex Gaynor 在 bpo-21307 中貢獻)
PEP 477: 將 ensurepip (PEP 453) 反向移植到 Python 2.7¶
PEP 477 批准在 Python 2.7 維護版本中包含 PEP 453 ensurepip 模組和由此實現的改進文件,首次出現在 Python 2.7.9 版本中。
預設引導 pip¶
新的 ensurepip
模組(定義於 PEP 453)提供了一種標準的跨平臺機制,用於將 pip 安裝程式引導到 Python 安裝中。Python 2.7.9 隨附的 pip
版本是 pip
1.5.6,未來的 2.7.x 維護版本將捆綁版本更新為建立候選釋出版本時可用的最新 pip
版本。
預設情況下,命令 pip
、pipX
和 pipX.Y
將在所有平臺上安裝(其中 X.Y 代表 Python 安裝的版本),以及 pip
Python 包及其依賴項。
對於 CPython 在 POSIX 系統上構建原始碼,make install
和 make altinstall
命令預設不引導 pip
。此行為可以透過配置選項控制,並透過 Makefile 選項覆蓋。
在 Windows 和 Mac OS X 上,CPython 安裝程式現在預設與 CPython 本身一起安裝 pip
(使用者可以在安裝過程中選擇不安裝)。Windows 使用者需要選擇自動 PATH
修改,以便預設情況下可以從命令列使用 pip
,否則仍然可以透過 Windows 的 Python 啟動器作為 py -m pip
訪問它。
如 PEP 中討論的,平臺打包者可以選擇預設不安裝這些命令,只要在呼叫時,它們提供關於如何在特定平臺上安裝這些命令的清晰簡單的說明(通常使用系統包管理器)。
文件更改¶
作為此更改的一部分,文件的 安裝 Python 模組 和 分發 Python 模組 部分已完全重新設計為簡短的入門和 FAQ 文件。大多數打包文件現已移至 Python 打包權威維護的 Python 打包使用者指南 和各個專案的文件。
然而,由於此遷移目前仍不完整,這些指南的舊版本仍可作為 使用 setuptools 構建 C 和 C++ 擴充套件 和 使用 setuptools 構建 C 和 C++ 擴充套件 提供。
參見
- PEP 453 – 在 Python 安裝中顯式引導 pip
PEP 由 Donald Stufft 和 Nick Coghlan 編寫,由 Donald Stufft、Nick Coghlan、Martin von Löwis 和 Ned Deily 實現。
PEP 476: 預設啟用 stdlib http 客戶端的證書驗證¶
PEP 476 更新了 httplib
和使用它的模組,例如 urllib2
和 xmlrpclib
,現在預設驗證伺服器是否提供了由平臺信任儲存中的證書頒發機構簽名的證書,並且其主機名與請求的主機名匹配,從而顯著提高了許多應用程式的安全性。此更改是在 Python 2.7.9 版本中進行的。
對於需要舊行為的應用程式,它們可以傳遞備用上下文
import urllib2
import ssl
# This disables all verification
context = ssl._create_unverified_context()
# This allows using a specific certificate for the host, which doesn't need
# to be in the trust store
context = ssl.create_default_context(cafile="/path/to/file.crt")
urllib2.urlopen("https://invalid-cert", context=context)
PEP 493: Python 2.7 的 HTTPS 驗證遷移工具¶
PEP 493 提供了額外的遷移工具,以支援包含在建立客戶端 HTTPS 連線時依賴於歷史上寬鬆處理伺服器證書的應用程式和服務的環境進行更漸進的基礎設施升級過程。這些新增是在 Python 2.7.12 版本中進行的。
這些工具旨在用於受影響的應用程式和服務無法修改為在建立連線時顯式傳遞更寬鬆的 SSL 上下文的情況。
對於根本無法修改的應用程式和服務,可以將新的 PYTHONHTTPSVERIFY
環境變數設定為 0
,以將整個 Python 程序恢復到 Python 2.7.8 及更早版本的預設寬鬆行為。
對於無法修改連線建立程式碼但可以修改整個應用程式的情況,可以使用新的 ssl._https_verify_certificates()
函式在執行時調整預設行為。
新的 make regen-all
構建目標¶
為了簡化交叉編譯,並確保 CPython 可以可靠地編譯而無需現有 Python 版本,基於 autotools 的構建系統不再嘗試根據檔案修改時間隱式重新編譯生成的檔案。
相反,已新增新的 make regen-all
命令,以便在需要時強制重新生成這些檔案(例如,在基於預生成版本構建了初始版本的 Python 之後)。
還定義了更具選擇性的重新生成目標——有關詳細資訊,請參閱 Makefile.pre.in。
(由 Victor Stinner 在 bpo-23404 中貢獻。)
在版本 2.7.14 中新增。
移除 make touch
構建目標¶
以前用於透過更新生成檔案的修改時間來請求隱式重新生成生成檔案的 make touch
構建目標已移除。
它已被新的 make regen-all
目標取代。
(由 Victor Stinner 在 bpo-23404 中貢獻。)
在版本 2.7.14 中更改。
致謝¶
作者要感謝以下人員為此文的各個草稿提供建議、更正和協助:Nick Coghlan、Philip Jenvey、Ryan Lovett、R. David Murray、Hugh Secker-Walker。