[Python] 在 xml.client.ServerProxy 中加入逾時 timeout 機制
專案從 Python 2 移轉到 Python 3 之後,
原本 IPC 機制裡使用到的 xmlrpc,
加上逾時 timeout 的機制不能用了,得重新在 Python 3 上實作…
上網找了一下,也有人在問 ServerProxy 為什麼不提供 timoeut 參數,
不過大大們的意見是這件事可以交給 Transport 來做,
不需要加在 ServerProxy 上面~
把大大們的範例碼拿來改一下,看起來應該是可以動。
先來做一個實驗的環境~
首先用 nc 跑一個 TCP server 聽在 port 19999,
假裝是一個不會回應的 xmlrpc server:
# nc -l -p 19999
接著,來看一下我們的 xmlrpc client 要怎麼寫吧~
我寫了一個 IPCClient
的類別,
裡面主要就是使用 xmlrpc.client.ServerProxy
來發出 XML RPC 的連線。
而逾期 timeout 的部分,則是建立一個 xmlrpc.client.Transport
物件,
並預先將其內部的 http.client.HTTPConnection
設定 timeout,
然後讓 xmlrpc.client.ServerProxy
使用這個 xmlrpc.client.Transport
物件,
這樣就可以在發出連線時,有逾時 timeout 的效果了:
import xmlrpc.client class IPCClient: def __init__(self, port, server="127.0.0.1", timeout=5): # Prepare a transport with timeout ipc_host = "%s:%d" % (server, port) transport = xmlrpc.client.Transport() conn = transport.make_connection(ipc_host) conn.timeout = timeout self._proxy = xmlrpc.client.ServerProxy('http://%s' % (ipc_host), transport=transport, allow_none=True) def call(self, func_name, *func_params): # Call the function with given parameters return getattr(self._proxy, func_name)(*func_params) if __name__ == "__main__": ipc_client = IPCClient(19999, timeout=3) print(ipc_client.call("debug"))
試著執行上面的程式,確實在 3 秒就會停止連線:
# time python3 ipcclient.py Traceback (most recent call last): File "ipcclient.py", line 21, in <module> print(ipc_client.call("debug")) File "ipcclient.py", line 16, in call result = getattr(self._proxy, func_name)(*func_params) File "/usr/lib64/python3.6/xmlrpc/client.py", line 1112, in __call__ return self.__send(self.__name, args) File "/usr/lib64/python3.6/xmlrpc/client.py", line 1452, in __request verbose=self.__verbose File "/usr/lib64/python3.6/xmlrpc/client.py", line 1154, in request return self.single_request(host, handler, request_body, verbose) File "/usr/lib64/python3.6/xmlrpc/client.py", line 1167, in single_request resp = http_conn.getresponse() File "/usr/lib64/python3.6/http/client.py", line 1346, in getresponse response.begin() File "/usr/lib64/python3.6/http/client.py", line 307, in begin version, status, reason = self._read_status() File "/usr/lib64/python3.6/http/client.py", line 268, in _read_status line = str(self.fp.readline(_MAXLINE + 1), "iso-8859-1") File "/usr/lib64/python3.6/socket.py", line 586, in readinto return self._sock.recv_into(b) socket.timeout: timed out real 0m3.368s user 0m0.323s sys 0m0.042s
在外部用 time 指令檢查執行時間,比較不準確,
因為會把程式啟動以及結束的時間都計入,
不過大概還是可以看出程式有依照 timeout 的時間在運作囉~
參考資料:問題 14134: xmlrpc.client.ServerProxy needs timeout parameter
(本頁面已被瀏覽過 466 次)