以串行对象为参数的多进程 [英] Multiprocess with Serial Object as Parameter

查看:89
本文介绍了以串行对象为参数的多进程的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在使用Python时遇到问题,并将串行对象作为参数传递给单独的进程.该程序正在Windows 8中运行,因此不能使用全局变量.

I'm having a problem with Python and passing a serial object as a parameter to a separate process. The program is being run in Windows 8, so using global variables isn't an option.

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()

程序运行时出现以下错误:

When the program runs I get the following error:


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似乎不喜欢那样.

If I place the open for the serial port (modemPort) as the first line of processIncomingSerialMessages the program works fine. The issue is that I need to decouple input and output from the modem so I need to pass the serial object as a parameter. And Python doesn't seem to like that.

任何人都可以看到我犯的错误,或者有人可以建议替代方法吗?

Can anyone see the mistake I am making, or can anyone suggest an alternative?

推荐答案

我无法运行此代码,但是如果它起作用,我会感到惊讶:跨进程传递的参数通过在发送端对参数对象进行腌制而起作用,通过管道或套接字在进程之间发送腌制字符串,并在接收端解开该字符串.我不知道任何打开的I/O种类的对象都可以工作的情况(文件,套接字,管道...). I/O类对象只是不具有内部数据状态,它们还连接到Python本身未实现的资源.泡菜只是原始字节流.

I can't run this code, but I'd be amazed if it worked: an argument passed across processes works by pickling the argument object on the sending side, sending the pickle string across processes via a pipe or a socket, and unpickling that string on the receiving side. I know of no case of any open I/O-kind-of-object for which this can possibly work (files, sockets, pipes ...). I/O-kinds-of-objects don't just have internal data state, they're also connected to resources that Python itself doesn't implement. A pickle is just a stream of raw bytes.

您已经确定必须在辅助进程中打开串行端口. las,我不知道我需要从调制解调器解耦输入和输出"的含义,因此很难提出解决方法.但是,我敢肯定,如果您接受已经发现的困难方法,就可以弄清楚:跨进程传递一个开放的串行对象永远不会起作用.

You already figured out that you have to open the serial port in the worker process. Alas, I don't know what "I need to decouple input and output from the modem" means, so it's hard to suggest a workaround. But I'm sure you'll figure it out if you accept what you've already discovered the hard way: passing an open serial object across processes is never going to work.

也就是说,您可以深入研究各种酸洗协议,并使用自定义的酸洗/酸洗代码构建自己的类,该代码在酸洗时会(重新)打开一个串行对象.这将是一种精心制作的方法,可以隐藏原本可以在工作进程中(重新)打开串行对象的简单代码.

That said, you could dig into the various pickling protocols and build your own class with custom pickling/unpickling code that (re)opened a serial object when unpickled. That would be an elaborate way to hide what would otherwise be straightforward code to (re)open a serial object in worker processes.

常见问题解答

再次,Windows无法提供退出全局变量的简便方法,因此我只能处理发送和接收的单个过程.

And again windows doesn't offer the easy way out of global variables, so I'm stuck with a single process handing both send and receive.

全局变量"可能对您没有帮助.我假设您想到的是fork(),但是在fork()之间没有任何共享:子进程请参见父进程地址空间的副本. I/O gi头通常也无法正常工作.

A "global variable" probably wouldn't help you. I assume you have fork() in mind, but nothing is shared across fork() either: child processes see copies of the parent process's address space. I/O gimmicks often fail to work correctly then too.

Python是否提供一种通过引用传递值或将引用值传递给进程的方法?我尝试将串行对象添加到具有相同结果的列表和集合中.再说一次,Python是否提供了Java的对象或数组之类的东西,我可以在不被腌烂"的情况下获得引用?

Does Python provide a way to pass a value by reference, or a reference value to a process? I have tried add the serial object to lists and sets with the same results. Again, does Python provide something like an Object or an Array from Java where I could get a reference through without it being "Pickled"?

在所有现代OS中,进程之间都有很高的隔离墙.为了使所有内容真正跨进程共享,您需要使用完全为此构建的类型,或者使用操作系统的共享内存"功能.

There's a very high wall between processes in all modern OSes. To get anything truly shared across processes you need to use types built from the ground up for that, or use the OS's "shared memory" facilities.

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

You can read the docs for multiprocessing.sharedctypes, which supplies ways to use shared (across processes) memory. But, as the docs warn:

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

Note Although it is possible to store a pointer in shared memory remember that this will refer to a location in the address space of a specific process. However, the pointer is quite likely to be invalid in the context of a second process and trying to dereference the pointer from the second process may cause a crash.

这是行不通的.这不是编程语言问题,而是操作系统问题. sharedctypes对于整数数组和浮点数数组很有用.

It's not going to work. This isn't a programming language issue, it's an OS issue. sharedctypes is useful for things like arrays of ints and floats.

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

For this application to work (live telemetry) the receive process has to remain live at all times.

对不起,我没有在上下文中关注它.您在问题中说:如果我将串行端口(modemPort)的开放位置放置为processIncomingSerialMessages的第一行,则程序运行正常." processIncomingSerialMessages之后有一个无限循环.从什么意义上说这违反了接收过程必须始终保持实时"?

Sorry, I'm not following that in context. You said in your question: "If I place the open for the serial port (modemPort) as the first line of processIncomingSerialMessages the program works fine.". processIncomingSerialMessages has an infinite loop following that. In what sense does that violate "the receive process has to remain live at all times"?

在您显示的代码中,看起来 没什么区别,无论是在工作进程中还是在主进程中打开了串行端口(如果后者确实起作用),确实,您说如果您采用前一种方法,它会很好用.那么,这样做到底有什么问题呢?确实,为什么要为此全部使用工作者进程?您显示的主程序在启动两个工作程序之后什么都没做(除了睡眠十分之一秒),所以为什么不让主程序 为接收进程"?

In the code you showed, it doesn't appear to make a lick of difference whether the serial port is opened in a worker process or in the main process (if the latter actually worked), and indeed you said it worked fine if you did it the former way. So what exactly is wrong with doing it that way? Indeed, why use a worker process at all for that? The main program you showed does nothing (except sleep for a tenth of a second) after starting both workers, so why not let the main program be "the receive process"?

这篇关于以串行对象为参数的多进程的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆