[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
(本頁面已被瀏覽過 576 次)