以串行对象为参数的多进程

时间:2014-01-01 21:44:29

标签: python parameters serial-port multiprocessing modem

我遇到了Python的问题,并将一个串行对象作为参数传递给一个单独的进程。该程序正在Windows 8中运行,因此使用全局变量不是一种选择。

from multiprocessing import Queue
from multiprocessing import Process
import os
import serial
from serial.tools import list_ports
from time import sleep

displayMessages = Queue()
modemPort = None

def processDisplayMessages(displayMessages):
    while True:
        msg = displayMessages.get()  #should halt until message in queue
        print msg

def processIncomingSerialMessages(modemPort, displayMessages):
    while True:
        line = modemPort.readline()
        displayMessages.put(line)

def main():
    print "Serial Send Test"
    Process(target=processDisplayMessages, args = (displayMessages,)).start()
    modemPort = serial.Serial('COM5', 57600, timeout=0.9)  # open first serial port
    Process(target=processIncomingSerialMessages, args = (modemPort, displayMessages)).start()
    print "Back from launch"

    sleep(0.1)

 if __name__ == '__main__':
    main()

当程序运行时,我收到以下错误:

Process Process-2:
Traceback (most recent call last):
  File "c:\python27\lib\multiprocessing\process.py", line 258, in _bootstrap
    self.run()
  File "c:\python27\lib\multiprocessing\process.py", line 114, in run
    self._target(*self._args, **self._kwargs)
  File "C:\Users\matthew.parets\Documents\..Development\RaspberryPi\windows\seri
alRecvPrototype.py", line 27, in processIncomingSerialMessages
    line = modemPort.readline()
  File "c:\python27\lib\site-packages\serial\serialwin32.py", line 246, in read
    if not self.hComPort: raise portNotOpenError
AttributeError: 'Serial' object has no attribute 'hComPort'

如果我将开放的串口(modemPort)作为processIncomingSerialMessages的第一行,程序运行正常。问题是我需要从调制解调器中分离输入和输出,因此我需要将串行对象作为参数传递。而Python似乎并不喜欢这样。

任何人都可以看到我犯的错误,或者有人可以提出替代方案吗?

1 个答案:

答案 0 :(得分:3)

我无法运行这段代码,但是如果它有用的话我会感到惊讶:跨越进程的参数通过在发送端pickle参数对象,通过管道或套接字在进程中发送pickle字符串来实现并在接收方取消该字符串。我知道没有任何可能有效的开放I / O类型的对象(文件,套接字,管道......)。 I / O类型的对象不具有内部数据状态,它们也连接到Python本身未实现的资源。 pickle只是一个原始字节流。

您已经发现必须在工作进程中打开串口。唉,我不知道“我需要从调制解调器中分离输入和输出”是什么意思,因此很难建议一种解决方法。但是我敢肯定,如果你接受了你已经发现的困难方法,你会明白这一点:在进程间传递一个开放的串行对象永远不会起作用。

也就是说,您可以深入了解各种酸洗协议,并使用自定义酸洗/去除代码来构建您自己的类,这些代码在重新打开时会重新打开一个串行对象。这将是一种精心设计的方法,可以隐藏在工作进程中(重新)打开一个串行对象的简单代码。

编辑:Q& A

  

再次,windows不提供全局变量的简单方法,所以我坚持使用单个进程处理发送和接收。

“全局变量”可能对您没有帮助。我假设您已考虑fork(),但fork()之间没有任何内容共享:子进程请参阅父进程地址空间的副本。 I / O噱头通常也无法正常工作。

  

Python是否提供了一种通过引用传递值或将引用值传递给进程的方法?我尝试将序列对象添加到列表和集合中,结果相同。再一次,Python是否提供类似于Java的对象或数组,我可以在不使用“Pickled”的情况下获得引用?

现代操作系统中的流程之间存在很大的障碍。要获得跨进程真正共享的任何内容,您需要使用从头开始构建的类型,或者使用操作系统的“共享内存”工具。

您可以阅读multiprocessing.sharedctypes的文档,它提供了使用共享(跨进程)内存的方法。但是,正如文档所警告的那样:

  

请注意   虽然可以将指针存储在共享内存中,但请记住这将引用特定进程的地址空间中的位置。但是,指针很可能在第二个进程的上下文中无效,并且尝试从第二个进程取消引用指针可能会导致崩溃。

它不会起作用。这不是编程语言问题,而是操作系统问题。 sharedctypes对于像int和float的数组这样的东西很有用。

  

要使此应用程序正常工作(实时遥测),接收过程必须始终保持在线状态。

抱歉,我不是在上下文中关注它。你在你的问题中说:“如果我把串口(modemPort)打开作为processIncomingSerialMessages的第一行,那么程序运行正常。” processIncomingSerialMessages之后有一个无限循环。在什么意义上违反了“接收过程必须始终保持在线”?

在您显示的代码中,无论是在工作进程中还是在主进程中打开串口(如果后者实际工作),它都不会出现来舔差异,事实上,如果你以前一种方式做到这一点,你说它工作正常。那么这样做究竟出了什么问题呢?实际上,为什么要使用工人流程呢?您启动两个工作程序后显示的主程序没有任何作用(除了睡眠十分之一秒),为什么不让主程序 “接收进程”?