代碼庫(kù)和插件 FAQ?
目錄
通用的代碼庫(kù)問(wèn)題?
如何找到可以用來(lái)做 XXX 的模塊或應(yīng)用??
在 代碼庫(kù)參考 中查找是否有適合的標(biāo)準(zhǔn)庫(kù)模塊。(如果你已經(jīng)了解標(biāo)準(zhǔn)庫(kù)的內(nèi)容,可以跳過(guò)這一步)
對(duì)于第三方軟件包,請(qǐng)搜索 Python Package Index 或者是嘗試 Google 或其他網(wǎng)絡(luò)搜索引擎。 搜索 "Python" 加上一兩個(gè)你感興趣的關(guān)鍵詞通常就會(huì)找到一些有用的信息。
math.py(socket.py,regex.py 等)的源文件在哪??
如果找不到模塊的源文件,可能它是一個(gè)內(nèi)建的模塊,或是使用 C,C++ 或其他編譯型語(yǔ)言實(shí)現(xiàn)的動(dòng)態(tài)加載模塊。這種情況下可能是沒(méi)有源碼文件的,類似 mathmodule.c
這樣的文件會(huì)存放在 C 代碼目錄中(但不在 Python 目錄中)。
Python 中(至少)有三類模塊:
使用 Python 編寫的模塊(.py);
使用 C 編寫的動(dòng)態(tài)加載模塊(.dll,.pyd,.so,.sl 等);
使用 C 編寫并鏈接到解釋器的模塊,要獲取此列表,輸入:
import sys print(sys.builtin_module_names)
在 Unix 中怎樣讓 Python 腳本可執(zhí)行??
你需要做兩件事:文件必須是可執(zhí)行的,并且第一行需要以 #!
開(kāi)頭,后面跟上 Python 解釋器的路徑。
第一點(diǎn)可以用執(zhí)行 chmod +x scriptfile
或是 chmod 755 scriptfile
做到。
第二點(diǎn)有很多種做法,最直接的方式是:
#!/usr/local/bin/python
在文件第一行,使用你所在平臺(tái)上的 Python 解釋器的路徑。
如果你希望腳本不依賴 Python 解釋器的具體路徑,你也可以使用 env 程序。假設(shè)你的 Python 解釋器所在目錄已經(jīng)添加到了 PATH
環(huán)境變量中,幾乎所有的類 Unix 系統(tǒng)都支持下面的寫法:
#!/usr/bin/env python
不要 在 CGI 腳本中這樣做。CGI 腳本的 PATH
環(huán)境變量通常會(huì)非常精簡(jiǎn),所以你必須使用解釋器的完整絕對(duì)路徑。
有時(shí)候,用戶的環(huán)境變量如果太長(zhǎng),可能會(huì)導(dǎo)致 /usr/bin/env 執(zhí)行失??;又或者甚至根本就不存在 env 程序。在這種情況下,你可以嘗試使用下面的 hack 方法(來(lái)自 Alex Rezinsky):
#! /bin/sh
""":"
exec python $0 ${1+"$@"}
"""
這樣做有一個(gè)小小的缺點(diǎn),它會(huì)定義腳本的 __doc__ 字符串。不過(guò)可以這樣修復(fù):
__doc__ = """...Whatever..."""
Python 中有 curses/termcap 包嗎??
對(duì)于類 Unix 系統(tǒng):標(biāo)準(zhǔn) Python 源碼發(fā)行版會(huì)在 Modules 子目錄中附帶 curses 模塊,但默認(rèn)并不會(huì)編譯。(注意:在 Windows 平臺(tái)下不可用 —— Windows 中沒(méi)有 curses 模塊。)
curses
模塊支持基本的 curses 特性,同時(shí)也支持 ncurses 和 SYSV curses 中的很多額外功能,比如顏色、不同的字符集支持、填充和鼠標(biāo)支持。這意味著這個(gè)模塊不兼容只有 BSD curses 模塊的操作系統(tǒng),但是目前仍在維護(hù)的系統(tǒng)應(yīng)該都不會(huì)存在這種情況。
Python 中存在類似 C 的 onexit() 函數(shù)的東西嗎??
atexit
模塊提供了一個(gè)與 C 的 onexit()
函數(shù)類似的注冊(cè)函數(shù)。
為什么我的信號(hào)處理函數(shù)不能工作??
最常見(jiàn)的問(wèn)題是信號(hào)處理函數(shù)沒(méi)有正確定義參數(shù)列表。它會(huì)被這樣調(diào)用:
handler(signum, frame)
因此它應(yīng)當(dāng)聲明為帶有兩個(gè)形參:
def handler(signum, frame):
...
通用任務(wù)?
怎樣測(cè)試 Python 程序或組件??
Python 帶有兩個(gè)測(cè)試框架。doctest
模塊從模塊的 docstring 中尋找示例并執(zhí)行,對(duì)比輸出是否與 docstring 中給出的是否一致。
unittest
模塊是一個(gè)模仿 Java 和 Smalltalk 測(cè)試框架的更棒的測(cè)試框架。
為了使測(cè)試更容易,你應(yīng)該在程序中使用良好的模塊化設(shè)計(jì)。程序中的絕大多數(shù)功能都應(yīng)該用函數(shù)或類方法封裝 —— 有時(shí)這樣做會(huì)有額外驚喜,程序會(huì)運(yùn)行得更快(因?yàn)榫植孔兞勘热肿兞吭L問(wèn)要快)。除此之外,程序應(yīng)該避免依賴可變的局部變量,這會(huì)使得測(cè)試?yán)щy許多。
程序的“全局主邏輯”應(yīng)該盡量簡(jiǎn)單:
if __name__ == "__main__":
main_logic()
并放置在程序主模塊的最后面。
一旦你的程序已經(jīng)組織為一個(gè)函數(shù)和類行為的有完整集合,你就應(yīng)該編寫測(cè)試函數(shù)來(lái)檢測(cè)這些行為。 可以將自動(dòng)執(zhí)行一系列測(cè)試的測(cè)試集關(guān)聯(lián)到每個(gè)模塊。 這聽(tīng)起來(lái)似乎需要大量的工作,但是由于 Python 是如此簡(jiǎn)潔靈活因此它會(huì)極其容易。 你可以通過(guò)與“生產(chǎn)代碼”同步編寫測(cè)試函數(shù)使編程更為愉快和有趣,因?yàn)檫@將更容易并更早發(fā)現(xiàn)代碼問(wèn)題甚至設(shè)計(jì)缺陷。
程序主模塊之外的其他“輔助模塊”中可以增加自測(cè)試的入口。
if __name__ == "__main__":
self_test()
通過(guò)使用 Python 實(shí)現(xiàn)的“假”接口,即使是需要與復(fù)雜的外部接口交互的程序也可以在外部接口不可用時(shí)進(jìn)行測(cè)試。
怎樣用 docstring 創(chuàng)建文檔??
pydoc
模塊可以用 Python 源碼中的 docstring 創(chuàng)建 HTML 文件。也可以使用 epydoc 來(lái)只通過(guò) docstring 創(chuàng)建 API 文檔。Sphinx 也可以引入 docstring 的內(nèi)容。
怎樣一次只獲取一個(gè)按鍵??
在類 Unix 系統(tǒng)中有多種方案。最直接的方法是使用 curses,但是 curses 模塊太大了,難以學(xué)習(xí)。
線程相關(guān)?
程序中怎樣使用線程??
一定要使用 threading
模塊,不要使用 _thread
模塊。threading
模塊對(duì) _thread
模塊提供的底層線程原語(yǔ)做了更易用的抽象。
我的線程都沒(méi)有運(yùn)行,為什么??
一旦主線程退出,所有的子線程都會(huì)被殺掉。你的主線程運(yùn)行得太快了,子線程還沒(méi)來(lái)得及工作。
簡(jiǎn)單的解決方法是在程序中加一個(gè)時(shí)間足夠長(zhǎng)的 sleep,讓子線程能夠完成運(yùn)行。
import threading, time
def thread_task(name, n):
for i in range(n):
print(name, i)
for i in range(10):
T = threading.Thread(target=thread_task, args=(str(i), i))
T.start()
time.sleep(10) # <---------------------------!
但目前(在許多平臺(tái)上)線程不是并行運(yùn)行的,而是按順序依次執(zhí)行!原因是系統(tǒng)線程調(diào)度器在前一個(gè)線程阻塞之前不會(huì)啟動(dòng)新線程。
簡(jiǎn)單的解決方法是在運(yùn)行函數(shù)的開(kāi)始處加一個(gè)時(shí)間很短的 sleep。
def thread_task(name, n):
time.sleep(0.001) # <--------------------!
for i in range(n):
print(name, i)
for i in range(10):
T = threading.Thread(target=thread_task, args=(str(i), i))
T.start()
time.sleep(10)
比起用 time.sleep()
猜一個(gè)合適的等待時(shí)間,使用信號(hào)量機(jī)制會(huì)更好些。有一個(gè)辦法是使用 queue
模塊創(chuàng)建一個(gè) queue 對(duì)象,讓每一個(gè)線程在運(yùn)行結(jié)束時(shí) append 一個(gè)令牌到 queue 對(duì)象中,主線程中從 queue 對(duì)象中讀取與線程數(shù)量一致的令牌數(shù)量即可。
如何將任務(wù)分配給多個(gè)工作線程??
最簡(jiǎn)單的方式是使用 concurrent.futures
模塊,特別是其中的 ThreadPoolExecutor
類。
或者,如果你想更好地控制分發(fā)算法,你也可以自己寫邏輯實(shí)現(xiàn)。使用 queue
模塊來(lái)創(chuàng)建任務(wù)列表隊(duì)列。Queue
類維護(hù)一個(gè)了一個(gè)存有對(duì)象的列表,提供了 .put(obj)
方法添加元素,并且可以用 .get()
方法獲取元素。這個(gè)類會(huì)使用必要的加鎖操作,以此確保每個(gè)任務(wù)只會(huì)執(zhí)行一次。
這是一個(gè)簡(jiǎn)單的例子:
import threading, queue, time
# The worker thread gets jobs off the queue. When the queue is empty, it
# assumes there will be no more work and exits.
# (Realistically workers will run until terminated.)
def worker():
print('Running worker')
time.sleep(0.1)
while True:
try:
arg = q.get(block=False)
except queue.Empty:
print('Worker', threading.current_thread(), end=' ')
print('queue empty')
break
else:
print('Worker', threading.current_thread(), end=' ')
print('running with argument', arg)
time.sleep(0.5)
# Create queue
q = queue.Queue()
# Start a pool of 5 workers
for i in range(5):
t = threading.Thread(target=worker, name='worker %i' % (i+1))
t.start()
# Begin adding work to the queue
for i in range(50):
q.put(i)
# Give threads time to run
print('Main thread sleeping')
time.sleep(5)
運(yùn)行時(shí)會(huì)產(chǎn)生如下輸出:
Running worker
Running worker
Running worker
Running worker
Running worker
Main thread sleeping
Worker <Thread(worker 1, started 130283832797456)> running with argument 0
Worker <Thread(worker 2, started 130283824404752)> running with argument 1
Worker <Thread(worker 3, started 130283816012048)> running with argument 2
Worker <Thread(worker 4, started 130283807619344)> running with argument 3
Worker <Thread(worker 5, started 130283799226640)> running with argument 4
Worker <Thread(worker 1, started 130283832797456)> running with argument 5
...
查看模塊的文檔以獲取更多信息;Queue
類提供了多種接口。
怎樣修改全局變量是線程安全的??
Python VM 內(nèi)部會(huì)使用 global interpreter lock (GIL)來(lái)確保同一時(shí)間只有一個(gè)線程運(yùn)行。通常 Python 只會(huì)在字節(jié)碼指令之間切換線程;切換的頻率可以通過(guò)設(shè)置 sys.setswitchinterval()
指定。從 Python 程序的角度來(lái)看,每一條字節(jié)碼指令以及每一條指令對(duì)應(yīng)的 C 代碼實(shí)現(xiàn)都是原子的。
理論上說(shuō),具體的結(jié)果要看具體的 PVM 字節(jié)碼實(shí)現(xiàn)對(duì)指令的解釋。而實(shí)際上,對(duì)內(nèi)建類型(int,list,dict 等)的共享變量的“類原子”操作都是原子的。
舉例來(lái)說(shuō),下面的操作是原子的(L、L1、L2 是列表,D、D1、D2 是字典,x、y 是對(duì)象,i,j 是 int 變量):
L.append(x)
L1.extend(L2)
x = L[i]
x = L.pop()
L1[i:j] = L2
L.sort()
x = y
x.field = y
D[x] = y
D1.update(D2)
D.keys()
這些不是原子的:
i = i+1
L.append(L[-1])
L[i] = L[j]
D[x] = D[x] + 1
覆蓋其他對(duì)象的操作會(huì)在其他對(duì)象的引用計(jì)數(shù)變成 0 時(shí)觸發(fā)其 __del__()
方法,這可能會(huì)產(chǎn)生一些影響。對(duì)字典和列表進(jìn)行大量操作時(shí)尤其如此。如果有疑問(wèn)的話,使用互斥鎖!
不能刪除全局解釋器鎖嗎??
global interpreter lock (GIL)通常被視為 Python 在高端多核服務(wù)器上開(kāi)發(fā)時(shí)的阻力,因?yàn)椋◣缀酰┧?Python 代碼只有在獲取到 GIL 時(shí)才能運(yùn)行,所以多線程的 Python 程序只能有效地使用一個(gè) CPU。
在 Python 1.5 時(shí)代,Greg Stein 開(kāi)發(fā)了一個(gè)完整的補(bǔ)丁包(“free threadings” 補(bǔ)?。瞥?GIL,并用粒度更合適的鎖來(lái)代替。Adam Olsen 最近也在他的 python-safethread 項(xiàng)目里做了類似的實(shí)驗(yàn)。不幸的是,由于為了移除 GIL 而使用了大量細(xì)粒度的鎖,這兩個(gè)實(shí)驗(yàn)在單線程測(cè)試中的性能都有明顯的下降(至少慢 30%)。
但這并意味著你不能在多核機(jī)器上很好地使用 Python!你只需將任務(wù)劃分為多*進(jìn)程*,而不是多*線程*。新的 concurrent.futures
模塊中的 ProcessPoolExecutor
類提供了一個(gè)簡(jiǎn)單的方法;如果你想對(duì)任務(wù)分發(fā)做更多控制,可以使用 multiprocessing
模塊提供的底層 API。
恰當(dāng)?shù)厥褂?C 拓展也很有用;使用 C 拓展處理耗時(shí)較久的任務(wù)時(shí),拓展可以在線程執(zhí)行 C 代碼時(shí)釋放 GIL,讓其他線程執(zhí)行。zlib
和 hashlib
等標(biāo)準(zhǔn)庫(kù)模塊已經(jīng)這樣做了。
也有建議說(shuō) GIL 應(yīng)該是解釋器狀態(tài)鎖,而不是完全的全局鎖;解釋器不應(yīng)該共享對(duì)象。不幸的是,這也不可能發(fā)生。由于目前許多對(duì)象的實(shí)現(xiàn)都有全局的狀態(tài),因此這是一個(gè)艱巨的工作。舉例來(lái)說(shuō),小整型數(shù)和短字符串會(huì)緩存起來(lái),這些緩存將不得不移動(dòng)到解釋器狀態(tài)中。其他對(duì)象類型都有自己的自由變量列表,這些自由變量列表也必須移動(dòng)到解釋器狀態(tài)中。等等。
我甚至懷疑這些工作是否可能在有限的時(shí)間內(nèi)完成,因?yàn)橥瑯拥膯?wèn)題在第三方拓展中也會(huì)存在。第三方拓展編寫的速度可比你將它們轉(zhuǎn)換為把全局狀態(tài)存入解釋器狀態(tài)中的速度快得多。
最后,假設(shè)多個(gè)解釋器不共享任何狀態(tài),那么這樣做比每個(gè)進(jìn)程一個(gè)解釋器好在哪里呢?
輸入與輸出?
怎樣刪除文件?(以及其他文件相關(guān)的問(wèn)題……)?
使用 os.remove(filename)
或 os.unlink(filename)
。查看 os
模塊以獲取更多文檔。這兩個(gè)函數(shù)是一樣的,unlink()
是這個(gè)函數(shù)在 Unix 系統(tǒng)調(diào)用中的名字。
如果要?jiǎng)h除目錄,應(yīng)該使用 os.rmdir()
;使用 os.mkdir()
創(chuàng)建目錄。os.makedirs(path)
會(huì)創(chuàng)建 path
中任何不存在的目錄。os.removedirs(path)
則會(huì)刪除其中的目錄,只要它們都是空的;如果你想刪除整個(gè)目錄以及其中的內(nèi)容,可以使用 shutil.rmtree()
。
重命名文件可以使用 os.rename(old_path, new_path)
。
如果需要截?cái)辔募?,使?f = open(filename, "rb+")
打開(kāi)文件,然后使用 f.truncate(offset)
;offset 默認(rèn)是當(dāng)前的搜索位置。也可以對(duì)使用 os.open()
打開(kāi)的文件使用 os.ftruncate(fd, offset)
,其中 fd 是文件描述符(一個(gè)小的整型數(shù))。
shutil
模塊也包含了一些處理文件的函數(shù),包括 copyfile()
,copytree()
和 rmtree()
。
怎樣復(fù)制文件??
shutil
模塊有一個(gè) copyfile()
函數(shù)。注意在 MacOS 9 中不會(huì)復(fù)制 resource fork 和 Finder info。
怎樣讀取(或?qū)懭耄┒M(jìn)制數(shù)據(jù)??
要讀寫復(fù)雜的二進(jìn)制數(shù)據(jù)格式,最好使用 struct
模塊。該模塊可以讀取包含二進(jìn)制數(shù)據(jù)(通常是數(shù)字)的字符串并轉(zhuǎn)換為 Python 對(duì)象,反之亦然。
舉例來(lái)說(shuō),下面的代碼會(huì)從文件中以大端序格式讀取一個(gè) 2 字節(jié)的整型和一個(gè) 4 字節(jié)的整型:
import struct
with open(filename, "rb") as f:
s = f.read(8)
x, y, z = struct.unpack(">hhl", s)
格式字符串中的 ‘>’ 強(qiáng)制以大端序讀取數(shù)據(jù);字母 ‘h’ 從字符串中讀取一個(gè)“短整型”(2 字節(jié)),字母 ‘l’ 讀取一個(gè)“長(zhǎng)整型”(4 字節(jié))。
對(duì)于更常規(guī)的數(shù)據(jù)(例如整型或浮點(diǎn)類型的列表),你也可以使用 array
模塊。
似乎 os.popen() 創(chuàng)建的管道不能使用 os.read(),這是為什么??
os.read()
是一個(gè)底層函數(shù),它接收的是文件描述符 —— 用小整型數(shù)表示的打開(kāi)的文件。os.popen()
創(chuàng)建的是一個(gè)高級(jí)文件對(duì)象,和內(nèi)建的 open()
方法返回的類型一樣。因此,如果要從 os.popen()
創(chuàng)建的管道 p 中讀取 n 個(gè)字節(jié)的話,你應(yīng)該使用 p.read(n)
。
怎樣訪問(wèn)(RS232)串口??
For Win32, OSX, Linux, BSD, Jython, IronPython:
對(duì)于 Unix,查看 Mitch Chapman 發(fā)布的帖子:
為什么關(guān)閉 sys.stdout(stdin,stderr)并不會(huì)真正關(guān)掉它??
Python 文件對(duì)象 是一個(gè)對(duì)底層 C 文件描述符的高層抽象。
對(duì)于在 Python 中通過(guò)內(nèi)建的 open()
函數(shù)創(chuàng)建的多數(shù)文件對(duì)象來(lái)說(shuō),f.close()
從 Python 的角度將其標(biāo)記為已關(guān)閉,并且會(huì)關(guān)閉底層的 C 文件描述符。在 f
被垃圾回收的時(shí)候,析構(gòu)函數(shù)中也會(huì)自動(dòng)處理。
但由于 stdin,stdout 和 stderr 在 C 中的特殊地位,在 Python 中也會(huì)對(duì)它們做特殊處理。運(yùn)行 sys.stdout.close()
會(huì)將 Python 的文件對(duì)象標(biāo)記為已關(guān)閉,但是*不會(huì)*關(guān)閉與之關(guān)聯(lián)的文件描述符。
要關(guān)閉這三者的 C 文件描述符的話,首先你應(yīng)該確認(rèn)確實(shí)需要關(guān)閉它(比如,這可能會(huì)影響到處理 I/O 的拓展)。如果確實(shí)需要這么做的話,使用 os.close()
:
os.close(stdin.fileno())
os.close(stdout.fileno())
os.close(stderr.fileno())
或者也可以使用常量 0,1,2 代替。
網(wǎng)絡(luò) / Internet 編程?
Python 中的 WWW 工具是什么??
參閱代碼庫(kù)參考手冊(cè)中 互聯(lián)網(wǎng)協(xié)議和支持 和 互聯(lián)網(wǎng)數(shù)據(jù)處理 這兩章的內(nèi)容。Python 有大量模塊來(lái)幫助你構(gòu)建服務(wù)端和客戶端 web 系統(tǒng)。
Paul Boddie 維護(hù)了一份可用框架的概覽,見(jiàn) https://wiki.python.org/moin/WebProgramming 。
Cameron Laird 維護(hù)了一份關(guān)于 Python web 技術(shù)的實(shí)用網(wǎng)頁(yè)的集合,見(jiàn) http://phaseit.net/claird/comp.lang.python/web_python 。
怎樣模擬發(fā)送 CGI 表單(METHOD=POST)??
我需要通過(guò) POST 表單獲取網(wǎng)頁(yè),有什么代碼能簡(jiǎn)單做到嗎?
是的。 這里是一個(gè)使用 urllib.request
的簡(jiǎn)單例子:
#!/usr/local/bin/python
import urllib.request
# build the query string
qs = "First=Josephine&MI=Q&Last=Public"
# connect and send the server a path
req = urllib.request.urlopen('http://www.some-server.out-there'
'/cgi-bin/some-cgi-script', data=qs)
with req:
msg, hdrs = req.read(), req.info()
注意,通常在百分號(hào)編碼的 POST 操作中,查詢字符串必須使用 urllib.parse.urlencode()
處理一下。舉個(gè)例子,如果要發(fā)送 name=Guy Steele, Jr.
的話:
>>> import urllib.parse
>>> urllib.parse.urlencode({'name': 'Guy Steele, Jr.'})
'name=Guy+Steele%2C+Jr.'
參見(jiàn)
查看 如何利用 urllib 包獲取網(wǎng)絡(luò)資源 獲取更多示例。
生成 HTML 需要使用什么模塊??
你可以在 Web 編程 wiki 頁(yè)面 找到許多有用的鏈接。
怎樣使用 Python 腳本發(fā)送郵件??
使用 smtplib
標(biāo)準(zhǔn)庫(kù)模塊。
下面是一個(gè)很簡(jiǎn)單的交互式發(fā)送郵件的代碼。這個(gè)方法適用于任何支持 SMTP 協(xié)議的主機(jī)。
import sys, smtplib
fromaddr = input("From: ")
toaddrs = input("To: ").split(',')
print("Enter message, end with ^D:")
msg = ''
while True:
line = sys.stdin.readline()
if not line:
break
msg += line
# The actual mail send
server = smtplib.SMTP('localhost')
server.sendmail(fromaddr, toaddrs, msg)
server.quit()
在 Unix 系統(tǒng)中還可以使用 sendmail。sendmail 程序的位置在不同系統(tǒng)中不一樣,有時(shí)是在 /usr/lib/sendmail
,有時(shí)是在 /usr/sbin/sendmail
。sendmail 手冊(cè)頁(yè)面會(huì)對(duì)你有所幫助。以下是示例代碼:
import os
SENDMAIL = "/usr/sbin/sendmail" # sendmail location
p = os.popen("%s -t -i" % SENDMAIL, "w")
p.write("To: receiver@example.com\n")
p.write("Subject: test\n")
p.write("\n") # blank line separating headers from body
p.write("Some text\n")
p.write("some more text\n")
sts = p.close()
if sts != 0:
print("Sendmail exit status", sts)
socket 的 connect() 方法怎樣避免阻塞??
通常會(huì)用 select
模塊處理 socket 異步 I/O。
要防止 TCP 連接發(fā)生阻塞,你可以將 socket 設(shè)為非阻塞模式。 這樣當(dāng)你執(zhí)行 socket.connect()
時(shí),你將或是立即完成連接(不大可能)或是收到一個(gè)包含 .errno
錯(cuò)誤碼的異常。 errno.EINPROGRESS
表示連接正在進(jìn)行但還沒(méi)有完成。 不同的操作系統(tǒng)將返回不同的值,因此你需要確認(rèn)你的系統(tǒng)會(huì)返回什么值。
你可以使用 socket.connect_ex()
方法來(lái)避免生成異常。 它將只返回 errno 值。 要進(jìn)行輪詢,你可以稍后再次調(diào)用 socket.connect_ex()
-- 0
或 errno.EISCONN
表示連接已完成 -- 或者你也可以將此 socket 傳給 select.select()
來(lái)檢查它是否可寫。
數(shù)據(jù)庫(kù)?
Python 中有數(shù)據(jù)庫(kù)包的接口嗎??
有的。
標(biāo)準(zhǔn) Python 還包含了基于磁盤的哈希接口例如 DBM
和 GDBM
。除此之外還有 sqlite3
模塊,該模塊提供了一個(gè)輕量級(jí)的基于磁盤的關(guān)系型數(shù)據(jù)庫(kù)。
大多數(shù)關(guān)系型數(shù)據(jù)庫(kù)都已經(jīng)支持。查看 數(shù)據(jù)庫(kù)編程 wiki 頁(yè)面 獲取更多信息。
在 Python 中如何實(shí)現(xiàn)持久化對(duì)象??
pickle
庫(kù)模塊以一種非常通用的方式解決了這個(gè)問(wèn)題(雖然你依然不能用它保存打開(kāi)的文件、套接字或窗口之類的東西),此外 shelve
庫(kù)模塊可使用 pickle 和 (g)dbm 來(lái)創(chuàng)建包含任意 Python 對(duì)象的持久化映射。
數(shù)學(xué)和數(shù)字?
Python 中怎樣生成隨機(jī)數(shù)??
random
標(biāo)準(zhǔn)庫(kù)模塊實(shí)現(xiàn)了隨機(jī)數(shù)生成器,使用起來(lái)非常簡(jiǎn)單:
import random
random.random()
這個(gè)函數(shù)會(huì)返回 [0, 1) 之間的隨機(jī)浮點(diǎn)數(shù)。
該模塊中還有許多其他的專門的生成器,例如:
randrange(a, b)
返回 [a, b) 區(qū)間內(nèi)的一個(gè)整型數(shù)。uniform(a, b)
返回 [a, b) 區(qū)間之間的浮點(diǎn)數(shù)。normalvariate(mean, sdev)
使用正態(tài)(高斯)分布采樣。
還有一些高級(jí)函數(shù)直接對(duì)序列進(jìn)行操作,例如:
choice(S)
從給定的序列中隨機(jī)選擇一個(gè)元素。shuffle(L)
會(huì)對(duì)列表執(zhí)行原地重排,即將其隨機(jī)地打亂。
還有 Random
類,你可以將其實(shí)例化,用來(lái)創(chuàng)建多個(gè)獨(dú)立的隨機(jī)數(shù)生成器。