Python 3.14下PySNMP Trap Receiver运行时错误排查求助
问题
我正在使用PySNMP 7.1.26与Python 3.14,开发了一个Trap Receiver并在子进程中启动,和主代码并行运行(暂未找到其他方案)。部分代码参考PySNMP示例:
from pysnmp.carrier.asyncio.dispatch import AsyncioDispatcher from pysnmp.carrier.asyncio.dgram import udp """跳过部分代码(回调函数定义)""" transportDispatcher = AsyncioDispatcher() transportDispatcher.register_recv_callback(__callback) # UDP/IPv4 transportDispatcher.register_transport( udp.DOMAIN_NAME, udp.UdpAsyncioTransport().open_server_mode((host, port)) ) transportDispatcher.job_started(1) try: transportDispatcher.run_dispatcher(timeout=time_out) finally: transportDispatcher.close_dispatcher()
该代码在Python 3.11至3.13中运行正常,但切换到3.14时出现运行时错误:
File "xxx\Python\Python314\Lib\multiprocessing\process.py", line 320, in _bootstrap self.run() File "xxx\Python\Python314\Lib\multiprocessing\process.py", line 108, in run self._target(*self._args, **self._kwargs) File "xxxy\venv314\Lib\site-packages\protocols\Snmp\SnmpTrapReceiver.py", line 93, in trap_listener_v1 transportDispatcher = AsyncioDispatcher() File "xxxx\Python\Python314\Lib\asyncio\events.py", line 715, in get_event_loop raise RuntimeError('There is no current event loop in thread %r.' % threading.current_thread().name) RuntimeError: There is no current event loop in thread 'MainThread'.
使用v3版本的Trap Receiver时也出现同类错误:
File "xxx\venv_314\Lib\site-packages\pysnmp\carrier\asyncio\dgram\base.py", line 100, in __init__ loop = asyncio.get_event_loop() File "xxx\Python\Python314\Lib\asyncio\events.py", line 715, in get_event_loop raise RuntimeError('There is no current event loop in thread %r.' % threading.current_thread().name) RuntimeError: There is no current event loop in thread 'MainThread'.
我发现Python 3.14中有一项变更:
asyncio.get_event_loop()现在在无当前事件循环时会抛出RuntimeError,不再隐式创建事件循环。
请问这是PySNMP的问题还是我遗漏了什么配置?这是否是问题的根本原因?
解答
这就是问题的根本原因。Python 3.14对asyncio.get_event_loop()的行为做了变更,而PySNMP 7.1.26的代码仍然依赖旧版本Python中该函数隐式创建事件循环的逻辑,在子进程的MainThread中没有预先生成事件循环时就会触发报错。
解决方法是在初始化PySNMP相关组件前,手动创建并设置asyncio事件循环,修改后的代码示例如下:
import asyncio from pysnmp.carrier.asyncio.dispatch import AsyncioDispatcher from pysnmp.carrier.asyncio.dgram import udp """跳过部分代码(回调函数定义)""" # 手动创建并设置事件循环 loop = asyncio.new_event_loop() asyncio.set_event_loop(loop) transportDispatcher = AsyncioDispatcher() transportDispatcher.register_recv_callback(__callback) # UDP/IPv4 transportDispatcher.register_transport( udp.DOMAIN_NAME, udp.UdpAsyncioTransport().open_server_mode((host, port)) ) transportDispatcher.job_started(1) try: transportDispatcher.run_dispatcher(timeout=time_out) finally: transportDispatcher.close_dispatcher()
另外,也可以考虑使用asyncio.run()来包裹事件循环的运行逻辑,但需要调整代码结构适配异步入口。不过对于子进程中的同步调用场景,手动创建并设置事件循环是最直接的修复方式。
如果后续PySNMP发布更新版本适配Python 3.14的asyncio行为,升级库即可无需手动处理事件循环。
内容的提问来源于stack exchange,提问作者juston
相关产品推荐
相关产品推荐

