當前位置:首頁 » 編程語言 » pythonsetblocking

pythonsetblocking

發布時間: 2022-06-21 11:20:26

⑴ 如何用python寫一個協程

作者:LittleCoder
鏈接:https://www.hu.com/question/54483694/answer/139785021
來源:知乎
著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請註明出處。

yield`和`yield from`的區別

`yield`題主肯定不陌生,而`yield from`是PEP 380中新增的一個特性。
PEP 380的名字是嵌套子迭代器的語法糖(我喜歡這么翻譯,原文是:Syntax for Delegating to a Subgenerator)。
既然是語法糖,那麼肯定本來是有別的寫法的,這里給出本來的寫法:
def subgen():
for i in range(3):
yield 'subgen: %s' % i
return 'subgen returned'def gen():
r = yield from subgen()
print('r = "%s"' % r)
yield rdef gen_without_yield_from():
sg = subgen()
try:
while 1:
yield sg.send(None)
except StopIteration as e:
yield e.valueprint('* [gen] get all values')for v in gen_without_yield_from():
print('get value: %s' % v)print('* [gen_without_yield_from] get all values')for v in gen_without_yield_from():
print('get value: %s' % v)

不難看出,`yield`子迭代器是把子迭代器直接傳遞出去,`yield from`子迭代器是把子迭代器的值一個一個傳出去。
雖然實際把子迭代器當做一個對象直接傳遞出去也沒有問題,也有使用場景(生成迭代器的迭代器)。
但在協程中相較於這個令人愉快的語法糖而言,直接傳遞就顯得沒有必要且礙事了。
畢竟我希望使用一個子迭代器是把子迭代器中的代碼都運行一遍而不是直接就把這個子迭代器傳出來讓我自己操作。
所以如果你把子迭代器直接傳了出去,asyncio就判斷你在做一件奇怪的事情並報了錯。
那麼,回到問題,給出的程序要怎麼通過`yield`調用呢?
# 源程序@asyncio.coroutinedef hello():
print("Hello world!")
yield from asyncio.sleep(1)
print("Hello again!")# 使用[email protected] hello():
print("Hello world!")
for v in asyncio.sleep(1):
yield v
print("Hello again!")

協程和迭代器的區別

舉個比喻,迭代器和協程就像火葯和槍械,利用火葯的特性輔助各種其他東西才造出了槍械。
迭代器就最簡單的本質而言就是一個可以暫停的程序。
那麼就有這樣一個合理的聯想,我是不是可以節省下所有不必要的例如等待網站響應的等待時間。
就是我把我的請求發過去以後就把這個程序暫停下來,開啟別的程序,等到響應來了再叫我回到這個程序。
那麼等待網站響應的時間也就完全沒有浪費了,比原來傻傻的等著網站響應真是優秀了許多。
這就是協程。
所以,為什麼看上去都是`generator`,迭代器不會天生成為協程呢?
因為沒有一個知道什麼時候應該叫你回到這個程序的人。
這個人就是`event_loop`(消息循環)。
回到問題,協程是否可以脫離`event_loop`(消息循環)調用。
講道理是不可以的,但合理聯想一下是不是一直不停的告訴程序又到你了就行了。
像這樣:
@asyncio.coroutinedef gen():
for i in range(3):
yield ifor i in gen():
print(i)print('end')

的確有些協程這樣是可以運行的(這些協程為什麼要寫成協程?)。
但終究你是在不應該告訴程序到你的時候告訴了他這件事情。
所以顯然獲取數據的話當時數據根本沒有傳到,`sleep`的話就根本沒有了`sleep`的效果。
只是看上去能夠運行,實際完全沒有用。
asyncio還為此特地加了一個斷言,如果你這樣調用`asyncio.sleep`,asyncio會發現你在偽裝消息循環騙他。
協程的原理

這是另一個看上去能夠運行,實際上完全沒有用的事情。
這雖然不是你想問的問題,但你已經碰到了也遲早會意識到,所以一並講了。
這個問題應該是這樣的:為什麼我寫出來的協程完全沒有協程的效果?
import time, [email protected] sleep(symbol, i):
time.sleep(i)
print('[%s] finished')loop = asyncio.get_event_loop()tasks = [sleep('A', 2), sleep('B', 2)]loop.run_until_complete(asyncio.wait(tasks))loop.close()

看到這里你起碼可以簡單的講出來,因為顯然我們在傻傻的等。
我們沒有在開始等待的時候把程序暫停下來,然後在等待結束後繼續運行程序,我們一心一意的在等。
我們真的`time.sleep`了兩秒,而不是去做了兩秒其他的事情。
你有各種選擇,可以花式等待。我這里給你兩個最基本的例子:
* get請求
* 同步變為協程(線程池)
get請求
為了讓你更好的了解asyncio,我從最底層的socket開始寫一個協程的get請求給你。
為了模擬延時很大的網站,我在本地開了一個延時伺服器,這是伺服器程序。
import tornado.ioloopimport tornado.webfrom tornado.gen import coroutine, sleepclass MainHandler(tornado.web.RequestHandler):
@coroutine
def get(self, waitTime=3):
yield sleep(int(waitTime))
self.write('you have waited for %ss' % waitTime)if __name__ == "__main__":
application = tornado.web.Application([
('/([0-9])', MainHandler),
], debug=True)
application.listen(5000)
try:
tornado.ioloop.IOLoop.current().start()
except:
tornado.ioloop.IOLoop.current().stop()

記得打開了這個伺服器再運行下面的程序。
import socket, asyncio, timedata = 'GET /%s HTTP/1.1\r\n\r\n'loop = asyncio.get_event_loop()@asyncio.coroutinedef get(i):
future = asyncio.futures.Future(loop=loop)
s = socket.socket()
s.connect(('127.0.0.1', 5000))
s.sendall((data % i).encode('utf8'))
s.setblocking(False)
def callback(future):
future.set_result(s.recv(999).split(b'\r\n\r\n')[-1])
loop.add_reader(s.fileno(), callback, future)
r = yield from future
print('Return value: %s' % r)tasks = [get(3), get(3)]loop.run_until_complete(asyncio.wait(tasks))loop.close()

同步變為協程(線程池)
這里拿sleep模擬耗時的程序,原理就是開了5個新的線程處理耗時程序。
當然實際的`asyncio.sleep`只需要告訴消息循環一定時間後叫醒我就好了。
import asyncio, sleep, [email protected] sleep(i):
executor = concurrent.futures.ThreadPoolExecutor(5)
future = asyncio.futures.wrap_future(executor.submit(time.sleep, i), loop=loop)
yield from future
print('Slept for %s seconds' % i)tasks = [sleep(3), sleep(3)]loop.run_until_complete(asyncio.wait(tasks))loop.close()

⑵ python的socket的非阻塞實現

setblocking(0)之後就是非阻塞的。

select模塊只是說能夠同時處理多個socket,至於這些socket是阻塞還是非阻塞,都沒有關系。當然從性能上考慮,現在的趨勢是select+非阻塞。

⑶ python3套接字udp設置接受數據超時

Sometimes,you need to manipulate the default values of certain properties of a socket library, for example, the socket timeout.

設定並獲取默認的套接字超時時間。

1.代碼

1 import socket
2
3
4 def test_socket_timeout():
5 s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
6 print("Default socket timeout: %s" % s.gettimeout())
7 # 獲取套接字默認超時時間
8 s.settimeout(100)
9 # 設置超時時間
10 print("Current socket timeout: %s" % s.gettimeout())
11 # 讀取修改後的套接字超時時間
12
13
14 if __name__ == '__main__':
15 test_socket_timeout()
2. AF_INET和SOCK_STREAM解釋

1 # 地址簇
2 # socket.AF_INET IPv4(默認)
3 # socket.AF_INET6 IPv6
4 # socket.AF_UNIX 只能夠用於單一的Unix系統進程間通信
5
6 # socket.SOCK_STREAM(數據流) 提供面向連接的穩定數據傳輸,即TCP/IP協議.多用於資料(如文件)傳送。
3.gettimeout()和settimeout()解釋

1 def gettimeout(self): # real signature unknown; restored from __doc__
2 """
3 gettimeout() -> timeout
4
5 Returns the timeout in seconds (float) associated with socket
6 operations. A timeout of None indicates that timeouts on socket
7 operations are disabled.
8 """
9 return timeout
10
11
12 def settimeout(self, timeout): # real signature unknown; restored from __doc__
13 """
14 settimeout(timeout)
15
16 Set a timeout on socket operations. 'timeout' can be a float,
17 giving in seconds, or None. Setting a timeout of None disables
18 the timeout feature and is equivalent to setblocking(1).
19 Setting a timeout of zero is the same as setblocking(0).
20 """
21 pass
22 # 設置套接字操作的超時期,timeout是一個浮點數,單位是秒。值為None表示沒有超時期。
23 # 一般,超時期應該在剛創建套接字時設置,因為它們可能用於連接的操作(如 client 連接最多等待5s )
4.運行結果

1 Default socket timeout: None
2 Current socket timeout: 100.0

⑷ python socketserver和socket的區別

區別:

1.首先介紹下socket

socket的英文原義是「孔」或「插座」。作為BSD UNIX的進程通信機制,取後一種意思。通常也
稱作"套接字",用於描述IP地址和埠,是一個通信鏈的句柄,可以用來實現不同虛擬機或不同計算機之間的通信。在Internet上的主機一 般運行了多個服務軟體,同時提供幾種服務。每種服務都打開一個Socket,並綁定到一個埠上,不同的埠對應於不同的服務。Socket正如其英文原 意那樣,像一個多孔插座。一台主機猶如布滿各種插座的房間,每個插座有一個編號,有的插座提供220伏交流電, 有的提供110伏交流電,有的則提供有線電視節目。 客戶軟體將插頭插到不同編號的插座,就可以得到不同的服務

內部調用流程為:

啟動服務端程序

執行 TCPServer.init方法,創建服務端Socket對象並綁定 IP 和 埠

執行 BaseServer.init方法,將自定義的繼承自SocketServer.BaseRequestHandler 的類 - MyRequestHandle賦值給 self.RequestHandlerClass

執行 BaseServer.server_forever 方法,While 循環一直監聽是否有客戶端請求到達 ...
當客戶端連接到達伺服器

執行 ThreadingMixIn.process_request 方法,創建一個 「線程」 用來處理請求

執行 ThreadingMixIn.process_request_thread 方法

執行 BaseServer.finish_request 方法,執行 self.RequestHandlerClass() 即:執行 自定義 MyRequestHandler 的構造方法(自動調用基類BaseRequestHandler的構造方法,在該構造方法中又會調用 MyRequestHandler的handle方法)

ForkingTCPServer

ForkingTCPServer和ThreadingTCPServer的使用和執行流程基本一致,只不過在內部分別為請求者建立 「線程」 和 「進程」。

⑸ python select可以設置成非阻塞嗎

setblocking(0)之後就是非阻塞的。 select模塊只是說能夠同時處理多個socket,至於這些socket是阻塞還是非阻塞,都沒有關系。當然從性能上考慮,現在的趨勢是select+非阻塞。

⑹ python socket 阻塞模式怎麼確保數據recv

可以通過setsockopt,或者更簡單的setblocking, settimeout設置。阻塞式的socket的recv服從這樣的規則:
當緩沖區內有數據時,立即返回所有的數據;當緩沖區內無數據時,阻塞直到緩沖區中有數據。非阻塞式的socket的recv服從的規則則是:
當緩沖區內有數據時,立即返回所有的數據;當緩沖區內無數據時,產生EAGAIN的錯誤並返回(在Python中會拋出一個異常)。兩種情況都不會返回空字元串,返回空數據的結果是對方關閉了連接之後才會出現的。

⑺ 小白求教,Python3實例類調用顯示沒定義

問下你的上述類代碼與main代碼都在同一個文件里嗎,如果在不同文件,有沒有import?

⑻ Python中socket里的.recv()函數問題

可以通過setsockopt,或者更簡單的setblocking,
settimeout設置。阻塞式的socket的recv服從這樣的規則:
當緩沖區內有數據時,立即返回所有的數據;當緩沖區內無數據時,阻塞直到緩沖區中有數據。非阻塞式的socket的recv服從的規則則是:
當緩沖區內有數據時,立即返回所有的數據;當緩沖區內無數據時,產生EAGAIN的錯誤並返回(在Python中會拋出一個異常)。兩種情況都不會返回空字元串,返回空數據的結果是對方關閉了連接之後才會出現的。

⑼ python怎麼做到socket的服務端和客戶端可以同時發送數據

建兩個socket不就可以了,模擬一個雙向信道啊

⑽ python無法立即完成一個非阻止性套接字操作

你使用了非阻塞模式,而10035表示數據還沒有返回給你。
你可以在接收前先select一下,如果有數據就接受,沒有就跳過。
你可參考python官方文檔
http://docs.python.org/howto/sockets.html
裡面有Non-blocking Sockets的一章可以看看。

import select
...
while 1:
infds,outfds,errfds = select.select([s,],[],[],5)
if len(infds) >0:
....
else:
print "no data coming"

熱點內容
取消微信設置密碼在哪裡設置 發布:2025-02-05 22:48:49 瀏覽:667
mysql內存存儲 發布:2025-02-05 22:30:39 瀏覽:570
靜態存儲區堆棧 發布:2025-02-05 22:09:11 瀏覽:102
js加密演算法 發布:2025-02-05 22:06:35 瀏覽:231
python3graphics 發布:2025-02-05 21:36:57 瀏覽:511
為什麼英雄聯盟一個伺服器進不去 發布:2025-02-05 21:36:12 瀏覽:182
伺服器搭建網站開發教材 發布:2025-02-05 21:31:57 瀏覽:567
pythonrose 發布:2025-02-05 21:31:46 瀏覽:923
php數組從小到大排序 發布:2025-02-05 21:26:01 瀏覽:325
單片機存儲器擴展 發布:2025-02-05 21:17:35 瀏覽:966