python - 如何管理 I/O 设备的多个唯一实例
问题描述
我有一个 I/O 串行设备(一个类,在这里调用它SerialPort
),我的程序的其他部分将读取/写入。SerialPort
处理与端口(pyserial)的连接,I/O 的线程化,并作为发布/订阅设计实现,如果有新消息,我程序中的其他类会被回调,或者可以编写新消息。该设备有超过 100 条支持的消息和响应,因此是 pub/sub 设计(不是这个问题的中心,只是想澄清选择)。
现在我需要添加 2 个(或更多)相同的设备。我想做的是让任何观察者调用类似的东西:
# The name of the devices and corresponding serial ports are known at run time. So in the program there will be N known devices.
# Where SerialPort("UniqueName1") is connected to port /dev/ttyUSB0
some_observer = Observer(SerialPort("UniqueName1"))
# Where SerialPort("UniqueName2") is connected to port /dev/ttyUSB2
other_observer = Observer(SerialPort("UniqueName2"))
# Here some_observer and random_observer both get the same instance of SerialPort("UniqueName1")
random_observer = Observer(SerialPort("UniqueName1"))
在 Observer() 中保存了 SerialPort 的实例(或接口),因此 Observer 可以编写并向 SerialPort 注册回调。我坚持的部分是如何处理对 SerialPort("UniqueName1") 的每次调用都应该返回已经连接的 SerialPort 对象(假设它之前已连接/初始化)。观察者应该只能说“我想与具有 UniqueName1(或 2)的设备交谈”
以这种方式,我可以通过在 Observer 中保留两个(或更多) SerialPort 引用来拥有两个 SerialPort 对象的观察者。我不需要这样做,但是如果我将来需要,这个设计不会限制我。
关于如何在 python (2.7) 中执行此操作的任何建议?我是 python 新手,边走边用谷歌搜索。我只需要帮助我应该将 python/伪代码放在下面的位置。我试图把它放在 Serialport 类中,但SerialPort.__init__(name)
没有让我返回一个已经创建的 SerialPort 设备
# Somewhere in the code
sp = SerialPort(name="UniqueName1")
# Now in SerialPort, where all_serial_ports = list of available SerialPorts
for serial_ports in all_serial_ports:
if serial_ports.name == name:
return serial_port
# Did not find serial port (need to do something)
解决方案
虽然可以拦截SerialPort
构造函数以便SerialPort("UniqueName1")
返回现有值(如果有)而不是创建新值,但1通常不是您想要做的。
最简单的解决方案是只存储串行端口的字典,但这需要每次手动查找:
if "UniqueName1" not in ports:
ports["UniqueName1"] = SerialPort("UniqueName1")
some_observer = Observer(ports["UniqueName1"])
因此,您可能希望将 dict 设为私有并将访问封装在一个函数中:
def getport(name):
if port not in _ports:
ports[name] = SerialPort(name)
return ports[name]
现在您只需调用该函数:
some_observer = Observer(getport("UniqueName1"))
您可以将此函数放在与您的SerialPort
或Observer
类相同的模块中。
如果您可能有多个不同的名称到端口的映射,您可能希望将其包装在一个SerialPortManager
类中,该类的实例具有一个self._ports
和一个getport
方法,否则您不需要它。
1.如果你真的想拦截构造函数,方法是使用__new__
方法。默认实现只返回一个新的类型的空对象,如果你返回它,你的__init__
方法就会被调用。但是你可以返回任何你想要的东西。其中包括不调用super()
版本,而是在一些私有字典中查找值。
推荐阅读
- python - 循环如何在基本计算机级别上工作?
- android - 仅在 Xamarin Android 中长按项目时显示工具栏图标
- amazon-web-services - AWS Fargate 任务抛出 Asm 获取用户名:AuthorizationData 格式错误,为空字段
- ios - SwiftUI | 在模拟器上找到文件但在 iOS 设备上找不到
- opengl - 如何使用曲面细分应用置换贴图?
- gitlab - Gitlab CI SAST 在下一阶段使用 gl-sast-report.json 报告的工件,使用了 2 种不同的扫描仪
- elasticsearch - 如何在 Elastic Cloud 中暂停 Elasticsearch?
- jquery - Wordpress/Gravity Forms - 如何根据选中的单选按钮显示/隐藏项目?
- java - 如何将表映射到 Java 对象
- mysql - COLLATION 'utf8mb4_unicode_ci' 对 CHARACTER SET 'utf8' 无效 - DB::connection