У меня есть модуль расширения C для CPython. Мне нужно несколько рабочих uWSGI, чтобы разделить один экземпляр объекта в этом модуле. Для этого я использую пользовательский подкласс multiprocessing.BaseManager
, основанный на этом ответе , который описывает очень похожее решение.
Первый скрипт ниже wifi.manager
(wifi.controller.IFace
- это объект для совместного использования). Я запускаю это с python3 wifi/manager.py
и затем запускаю веб-сервер, который запускает код во втором фрагменте для получения экземпляра общего объекта.
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
. Иногда я хочу быть в состоянии перехватить их в веб-приложении, чтобы представить клиенту значимые страницы ошибок. Но иногда я замечал, что эти исключения регистрируются, и в веб-приложении возникает то же исключение (например, WifiError
). В других случаях веб-приложение получает multiprocessing.managers.RemoteError
с трассировкой от менеджера, сохраненной в виде строки.
Вопрос в том, как я узнаю, когда оно вызовет исходное исключение, а когда оно вызовет RemoteError
, чтобы я знал, какое из них перехватить? Все документы Python говорят это:
Если исключение вызвано вызовом, то повторно вызывается _callmethod (). Если в процессе менеджера возникает какое-то другое исключение, оно преобразуется в исключение RemoteError и вызывается функцией _callmethod ().
Это не очень понятно для меня, и я не могу понять, как это согласуется с поведением, которое я наблюдал.