为什么在使用类时会出现“循环已运行”的情况?

huangapple go评论50阅读模式
英文:

Why do i get loop already running when using classes

问题

现在我只翻译代码部分,其他的问题请告诉我。

# 导入模块
import asyncio
import serial_asyncio
from async_serial_output import OutputProtocol, InputChunkProtocol
import logging

# 定义EboxAndino类
class EboxAndino():
    """
    Class which manages the connection to the serial port
    """
    # 类变量
    ebox = None
    timeout: int
    counter1Opc = None
    counter2Opc = None
    input1Opc = None
    input2Opc = None
    Heartbeat = None
    logger = None
    debug = False
    setup_dict = {}
    counterValueDict = {}

    hwPort = None
    baud = None
    timeout = None
    debug = False
    logger = logging.getLogger('foo')
    hBeat = False
    ser = None
    rts = False

    # 初始化方法
    def __init__(self, ebox, hwPort, baud, timeout, debug, loggerName) -> None:
        """
        @param ebox: opcObj
        @param hwPort: string
        @param baud: int
        @param timeout: int
        @param debug: bool
        @param loggerName: string
        """
        # 初始化实例变量
        self.ebox = ebox
        self.hwPort = hwPort
        self.baud = baud
        self.timeout = timeout
        self.debug = debug
        self.hBeat = False
        self.ser = None
        self.rts = False
        print('created!')

    # 异步初始化计数器方法
    async def initCounter(self):
        self.hBeat = False
        self.counterValueDict = {"Counter1": None,
                                "Counter2": None,
                                "Input1": None,
                                "Input2": None,
                                }
        setup_list = [*self.counterValueDict]
        print('Counter is up!')

    # 获取值方法
    def get_values(self):
        if self.counterValueDict:
            return self.counterValueDict
        else:
            return None

    # 异步读取串口数据方法
    async def line_reader(self, loop):
        coro = await serial_asyncio.create_serial_connection(loop, OutputProtocol, '/dev/ttyAMA0', baudrate=38400)
        await asyncio.sleep(1)
        transport, protocol = loop.run_until_complete(coro)
        await asyncio.sleep(0.5)
        loop.run_forever()
        loop.close()

# 异步主函数
async def main():
    # 获取事件循环
    loop = asyncio.get_event_loop()
    # 创建EboxAndino实例
    andino = EboxAndino('foo', '/dev/ttyAMA0', 38400, 1, True, 'foo')
    # 异步初始化计数器
    await andino.initCounter()
    # 异步读取串口数据
    await andino.line_reader(loop)

# 获取事件循环
loop = asyncio.get_event_loop()
# 异步休眠2秒
asyncio.sleep(2)
# 运行主函数
loop.run_until_complete(main())
英文:

So i am trying to read data from a serial port with python.

I am planning on feeding this data to my asyncua server in the future.
Comming from c# i always have the urge to make classes.
However when i run the code i get the Exception that the loop is already running.

As far as i understood tasks will be put into the loop and then executed so i think i am missing something here.

From a best practice approach does it make sense to make classes in python like this or is there a "better" way? I appreciate all input.

I have made a Class which is supposed to handle the reading from the serial port and later should assign the value to the nodes on the opc server.

For the reading i used the examples made here
pySerialDocumentation

import asyncio
import serial_asyncio
from async_serial_output import OutputProtocol,InputChunkProtocol
import logging
class EboxAndino():
"""
Class which manages the connection to the serial port
"""
ebox = None
timeout: int
counter1Opc = None
counter2Opc = None
input1Opc = None
input2Opc = None
Heartbeat = None
logger = None
debug = False
setup_dict = {}
counterValueDict = {}
hwPort = None
baud = None
timeout = None
debug = False
logger = logging.getLogger('foo')
hBeat = False
ser = None
rts = False
def __init__(self, ebox, hwPort, baud, timeout, debug, loggerName) -> None:
"""
@param ebox: opcObj
@param hwPort: string
@param baud: int
@param timeout: int
@param debug: bool
@param loggerName: string
"""
# self = EboxAndino('Ebox')
self.ebox = ebox
self.hwPort = hwPort
self.baud = baud
self.timeout = timeout
self.debug = debug
self.hBeat = False
self.ser = None
self.rts = False
print('created!')
async def initCounter(self):
self.hBeat = False
self.counterValueDict = {"Counter1": None,
"Counter2": None,
"Input1": None,
"Input2": None,
}
setup_list = [*self.counterValueDict]
print ('Counter is up!')
def get_values(self):
if self.counterValueDict:
return self.counterValueDict
else:
return None
async def line_reader(self,loop):
coro = await serial_asyncio.create_serial_connection(loop, OutputProtocol, '/dev/ttyAMA0', baudrate = 38400)
await asyncio.sleep(1)
transport, protocol = loop.run_until_complete(coro)
await asyncio.sleep(0.5)
loop.run_forever()
loop.close()

With my main beeing

async def main():
loop = asyncio.get_event_loop()
andino = EboxAndino('foo', '/dev/ttyAMA0', 38400, 1, True, 'foo')
await andino.initCounter()
await andino.line_reader(loop)
loop = asyncio.get_event_loop()
asyncio.sleep(2)
loop.run_until_complete(main())

Running this will give me the first line split into 4 recieved packages.
After it it will get an exception that the loop is already running.
Why?

As a follow up question where would be the best place to grab and store the values to the opc server?

Thank you everyone!

答案1

得分: 1

在asyncio中,你只能运行一个循环。你使用的示例是用于同步上下文的。但是现在你已经在异步上下文中了,所以不需要调用loop.run_until。

async def line_reader(self, loop):
    transport, protocol = await serial_asyncio.create_serial_connection(loop, OutputProtocol, '/dev/ttyAMA0', baudrate=38400)
    await asyncio.sleep(1)
    await asyncio.sleep(0.5)
英文:

In asyncio you can only run one loop.
The example you use is for an synchrnous context. But you are now in the async context already. So there is no need to call loop.run_until.

 async def line_reader(self,loop):
transport, protocol = await serial_asyncio.create_serial_connection(loop, OutputProtocol, '/dev/ttyAMA0', baudrate = 38400)
await asyncio.sleep(1)
await asyncio.sleep(0.5)

huangapple
  • 本文由 发表于 2023年5月10日 18:37:08
  • 转载请务必保留本文链接:https://go.coder-hub.com/76217392.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定