英文:
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)
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论