[Python] 在 xml.client.ServerProxy 中加入逾時 timeout 機制

[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 次)

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *

這個網站採用 Akismet 服務減少垃圾留言。進一步了解 Akismet 如何處理網站訪客的留言資料