簡體   English   中英

multiprocessing.BaseManager何時使用RemoteError?

[英]When does multiprocessing.BaseManager use RemoteError?

我有一個用於CPython的C擴展模塊。 我需要多個uWSGI worker才能在這個模塊中共享一個對象的單個實例。 我正在使用multiprocessing.BaseManager的自定義子類來完成此任務,基於此答案描述了一個非常類似的解決方案。

下面的第一個腳本是wifi.managerwifi.controller.IFace是要共享的對象)。 我使用python3 wifi/manager.py運行它,然后啟動Web服務器,它運行第二個代碼段中的代碼以獲取共享對象實例。

WIFI / manager.py:

#!/usr/bin/env python3

from multiprocessing.managers import BaseManager

# .register() changes the class itself. We don't want to do that to BaseManager.
class WifiManager(BaseManager):
    pass

if __name__ == '__main__':
    # If we are executed as a script (python3 manager.py), start the server
    import atexit
    from multiprocessing import Lock
    import wifi.controller

    ifaces_lock = Lock()
    ifaces = dict()

    def get_iface(iface_path):
        with ifaces_lock:
            if iface_path not in ifaces:
                # Control interface isn't open. Open it.
                iface = wifi.controller.IFace(iface_path)
                ifaces[iface_path] = iface
        return ifaces[iface_path]

    def close_ifaces():
        for iface in ifaces.values():
            iface.close()

    WifiManager.register('get_iface', get_iface)
    atexit.register(close_ifaces)

    manager = WifiManager(address=('127.0.0.1', 2437), authkey=b'wifimanager')
    server = manager.get_server()
    server.serve_forever()
else:
    # If we are imported, provide the WifiManager class ready for clients to use
    WifiManager.register('get_iface')

來自網絡應用程序的代碼段:

from wifi.manager import WifiManager

...

wmanager = WifiManager(address=('127.0.0.1', 2437), authkey=b'wifimanager')
wmanager.connect()
iface = wmanager.get_iface(iface_path)

iface.scan() # And other code using the iface object

wifi.controller.IFace對象有時會引發異常,無論是內置的(主要是OSError )還是自己的wifi.controller.WifiError異常。 有時,我希望能夠在Web應用程序中捕獲這些內容,以向客戶端顯示有意義的錯誤頁面。 但是,我注意到有時候,這些異常會被捕獲並且在Web應用程序中引發相同的異常(例如WifiError )。 其他時候,Web應用程序會獲得一個multiprocessing.managers.RemoteError ,其中來自管理器的回溯存儲為字符串。

問題是,我怎么知道它什么時候會引發原始異常以及何時會引發RemoteError ,所以我知道要捕獲哪一個? 所有Python文檔都說

如果調用引發異常,則由_callmethod()重新引發。 如果在管理器的進程中引發了一些其他異常,則會將其轉換為RemoteError異常並由_callmethod()引發。

這對我來說不是很清楚,我無法弄清楚它是如何與我觀察到的行為對齊的。

我相信我已經明白了。 我仍然不是百分百肯定,但看到這個問題沒有得到很多關注,我想我會繼續並添加一個答案,以防未來的讀者偶然發現。

在原始遠程調用期間在WifiManager中發生的異常會被引發為RemoteError 在這種情況下,這意味着在Web應用程序中此行期間遠程端的異常:

iface = wmanager.get_iface(iface_path)

之后,Web應用程序不再直接與WifiManager交互。 它只與iface代理對象)進行交互。 如果代理對象(或更准確地說,它的引用對象)在遠程端引發異常, RemoteError在Web應用程序中引發相同的異常,而不是RemoteError 因此,這意味着如果此行導致例如WifiErrorOSError ,那么這些是您將捕獲的異常:

iface.scan() # And other code using the iface object

因此,總而言之,當遠程端出現異常時BaseManager (或子類)的調用會引發RemoteError 對代理對象的調用會引發原始異常的副本。

請記住,這個答案是基於我的觀察,而不是我對情況的全面和全面的了解,所以我可能沒有意識到這里有一些問題。 如果有人知道的更好,請糾正我。 但這描述了我觀察到的行為,並且似乎與問題中引用的文檔一致。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM