asyncio“任务已被销毁,但正在等待处理!”在 pysnmp 示例程序中

问题描述 投票:0回答:2

我正在测试 pysnmp asyncio 模块,并开始使用随文档一起提供的 示例程序。当我运行示例程序时,它给出了

Task was destroyed but it is pending!
错误。我检查了类似的问题,但找不到我(缺乏经验的)眼睛的问题。我正在使用 Python 3.4.2 和它附带的 asyncio 以及 Debian 8.5 上的 pysnmp (4.3.2)

我使用的程序(与pysnmp文档中的示例程序相同)

 
    import asyncio
    from pysnmp.hlapi.asyncio import *


    @asyncio.coroutine
    def getone(snmpEngine, hostname):
        errorIndication, errorStatus, errorIndex, varBinds = yield from getCmd(
            snmpEngine,
            CommunityData('public'),
            UdpTransportTarget(hostname),
            ContextData(),
            ObjectType(ObjectIdentity('SNMPv2-MIB', 'sysDescr', 0))
        )

        if errorIndication:
            print(errorIndication)
        elif errorStatus:
            print('%s at %s' % (
                errorStatus.prettyPrint(),
                errorIndex and varBinds[int(errorIndex) - 1][0] or '?'
            )
                  )
        else:
            for varBind in varBinds:
                print(' = '.join([x.prettyPrint() for x in varBind]))


    @asyncio.coroutine
    def getall(snmpEngine, hostnames):
        for hostname in hostnames:
            yield from getone(snmpEngine, hostname)


    snmpEngine = SnmpEngine()

    loop = asyncio.get_event_loop()
    loop.run_until_complete(getall(snmpEngine, [('demo.snmplabs.com', 1161),
                                                ('demo.snmplabs.com', 2161),
                                                ('demo.snmplabs.com', 3161)]))
  

错误是:

 

     Executing  wait_for= cb=[_raise_stop_error() at /usr/lib/python3.4/asyncio/base_event
    s.py:101] created at /usr/lib/python3.4/asyncio/base_events.py:264> took 0.460 seconds
    SNMPv2-MIB::sysDescr.0 = SunOS zeus.snmplabs.com 4.1.3_U1 1 sun4m
    SNMPv2-MIB::sysDescr.0 = SunOS zeus.snmplabs.com 4.1.3_U1 1 sun4m
    SNMPv2-MIB::sysDescr.0 = SunOS zeus.snmplabs.com 4.1.3_U1 1 sun4m
    Task was destroyed but it is pending!
    source_traceback: Object created at (most recent call last):
      File "multiple-sequential-queries.py", line 58, in 
        ('demo.snmplabs.com', 3161)]))   
      File "/usr/lib/python3.4/asyncio/base_events.py", line 271, in run_until_complete
        self.run_forever()
      File "/usr/lib/python3.4/asyncio/base_events.py", line 244, in run_forever
        self._run_once()
      File "/usr/lib/python3.4/asyncio/base_events.py", line 1075, in _run_once
        handle._run()
      File "/usr/lib/python3.4/asyncio/events.py", line 120, in _run
        self._callback(*self._args)
      File "/usr/lib/python3.4/asyncio/tasks.py", line 237, in _step
        result = next(coro)
      File "/usr/lib/python3.4/asyncio/coroutines.py", line 79, in __next__
        return next(self.gen)
      File "multiple-sequential-queries.py", line 50, in getall
        yield from getone(snmpEngine, hostname)
      File "/usr/lib/python3.4/asyncio/coroutines.py", line 79, in __next__
        return next(self.gen)
      File "multiple-sequential-queries.py", line 31, in getone
        ObjectType(ObjectIdentity('SNMPv2-MIB', 'sysDescr', 0))
      File "/usr/lib/python3.4/asyncio/coroutines.py", line 79, in __next__
        return next(self.gen)
      File "/usr/lib/python3.4/asyncio/coroutines.py", line 141, in coro
        res = func(*args, **kw)
      File "/usr/local/lib/python3.4/dist-packages/pysnmp/hlapi/asyncio/cmdgen.py", line 138, in getCmd
        addrName, paramsName = lcd.configure(snmpEngine, authData, transportTarget)
      File "/usr/local/lib/python3.4/dist-packages/pysnmp/hlapi/lcd.py", line 87, in configure
        transport
      File "/usr/local/lib/python3.4/dist-packages/pysnmp/entity/config.py", line 308, in addTransport
        transport)
      File "/usr/local/lib/python3.4/dist-packages/pysnmp/carrier/asyncio/dispatch.py", line 70, in registerTransport
        self.loopingcall = asyncio.async(self.handle_timeout())
    task: :4> wait_for= created at /usr/local/lib/python3.4/dist-packages/pysnmp/carrier/asyncio/dispatch.py:70>

 

非常感谢任何解决此问题的帮助!

谢谢。

python python-3.x python-asyncio pysnmp
2个回答
1
投票

pysnmp 中有一个内部计时器函数,用于处理缓存、重试等。使用 asyncio 传输时,计时器由 asyncio 驱动

Future
。您观察到的消息警告您,在主循环关闭之前,Future 对象仍处于待处理状态。

要解决此问题,您需要在完成所有 SNMP I/O 后取消挂起的计时器任务。一种[黑客]方法是将以下代码片段附加到您提到的示例脚本中:

...

snmpEngine = SnmpEngine()

loop = asyncio.get_event_loop()

loop.run_until_complete(getall(snmpEngine, [('demo.snmplabs.com', 1161),
                                            ('demo.snmplabs.com', 2161),
                                            ('demo.snmplabs.com', 3161)]))

# run a coroutine to cancel pending timer task

from pysnmp.hlapi.asyncore.cmdgen import lcd

@asyncio.coroutine
def unconfigure(snmpEngine, authData=None):
    lcd.unconfigure(snmpEngine, authData)

loop.run_until_complete(unconfigure(snmpEngine))

我正在努力将类似的协程添加到 pysnmp 中,以便您可以开箱即用地运行它。


0
投票

作为这个库的新维护者,我们团队与 Ilya 持有不同的意见。

就像我们在这个 GitHub 问题中解释的那样,

SnmpEngine
类型的用户应该通过调用
SnmpEngine.transportDispatcher.closeDispatcher()
来显式释放资源(包括任务)。

© www.soinside.com 2019 - 2024. All rights reserved.