简体   繁体   English

在多个并行运行的python程序之间进行通信

[英]Communicating between multiple python programs running in parallel

Here's a summary of my setup: 以下是我的设置摘要:

  • 3 axis CNC, controllable via a python script running on raspberry pi 3轴CNC,可通过在树莓派上运行的python脚本进行控制
  • Windows PC can connect to the pi can run a script Windows PC可以连接到pi可以运行脚本

The end goal is for a UI made in C# to initiate an automated test cycle for the CNC to run in. In the python program there is a Cnc object that stores the devices current position and contains methods to position it to a certain place. 最终目标是使用C#制作的UI来启动要运行的CNC的自动化测试周期。在python程序中,有一个Cnc对象,该对象存储设备的当前位置并包含将其定位到特定位置的方法。

The problem is if i run a new script every time i want to move the CNC, I have to re initialize the Cnc instance and it will forget it's position. 问题是,如果我每次要移动CNC时都运行一个新脚本,则必须重新初始化Cnc实例,它将忘记它的位置。 So I'm wondering if I can have one master program running that contains the one and only Cnc instance, then when the remote machine wants to tell the CNC to move it can run a different script with argz for the new position python action.py xyz . 所以我想知道是否可以运行一个包含一个唯一的Cnc实例的主程序,那么当远程计算机想要告诉CNC移动时,它可以为新位置python action.py xyz运行带有argz的不同脚本。 python action.py xyz This script could then communicate to the master program to call the move method to the appropriate location without ever having to re-construct a new Cnc object. 然后,该脚本可以与主程序进行通信,以将move方法调用到适当的位置,而不必重新构造新的Cnc对象。 Then ideally the master program would indicate when the motion is completed and send back a message to the "action" script, that script would output something to tell the remote system that the action is completed, then it would exit, ready to be called again with new argz. 然后,理想情况下,主程序将指示运动何时完成,并将消息发送回“动作”脚本,该脚本将输出一些内容以告知远程系统动作已完成,然后退出,准备再次调用与新的argz。

In the end the remote system is highly abstracted from any of the working and just needs to start running the master, then run the move script with argz any time it wants to perform a motion. 最后,远程系统从任何工作中都高度抽象化,只需要开始运行主系统,然后在需要执行运动的任何时候使用argz运行move脚本。

Note: My other idea was to just save a text file with the current position then always re initialize the instance with the info in the file. 注意:我的另一个想法是只保存当前位置的文本文件,然后始终使用文件中的信息重新初始化实例。

EDIT: SOLVED... sort of 编辑:解决...有点

handler.py handler.py

The handler will continuously read from a text file named input.txt looking for a new integer. 处理程序将不断从名为input.txt的文本文件中读取,以寻找新的整数。 If received it will update a text file named output.txt to read '0', then do some action with the input (ie move a cnc) then write the value '1' to output.txt. 如果收到,它将更新一个名为output.txt的文本文件,使其读为“ 0”,然后对输入进行一些操作(即移动一个cnc),然后将值“ 1”写入output.txt。

from time import sleep
cur_pos=0

while True:
    with open("input.txt","r") as f:
        pos=f.readline()
    try:
        if pos=='':
            pass
        else:
            pos=int(pos)
    except:
        print pos
        print("exititng...")
        exit()

    if cur_pos==pos or pos=='':
        #suggestion from @Todd W to sleep before next read
        sleep(0.3)
        pass
    else:
        print("Current pos: {0:d}, New pos: {1:d}".format(cur_pos,pos))
        print("Updating...")
        with open("output.txt","w") as f:
            f.write("0")
        #do some computation with the data
        sleep(2)
        cur_pos=pos
        print("Current pos: {0:d}".format(cur_pos))
        with open("output.txt","w") as f:
            f.write("1")

pass_action.py pass_action.py

The action passer will accept a command line argument, write it to input.txt, then wait for output.txt to read '1', after which it will print done and exit. 操作传递者将接受命令行参数,将其写入input.txt,然后等待output.txt读取为“ 1”,此后它将打印完成并退出。

import sys
from time import sleep
newpos=sys.argv[1]
with open("input.txt","w") as f:
    f.write(newpos)

while True:
    sleep(0.1)
    with open("output.txt","r") as f:
        if f.readline()=='1':
            break

sys.stdout.write("done")

One possible approach might just be to make your main python script a webapp using something like Flask or Bottle . 一种可能的方法可能只是使用Flask或Bottle来使您的主要python脚本成为webapp。 Your app initializes the cnc, then waits for HTTP input, maybe on an endpoint like 'move'. 您的应用程序初始化cnc,然后等待HTTP输入,可能在“ move”之类的端点上。 Your C# app then just sends a REST request (HTTP) to move like {'coordinates': [10,15]} and your app acts on it. 然后,您的C#应用​​程序仅发送一个REST请求(HTTP)进行移动,就像{'coordinates': [10,15]} ,您的应用程序将对此进行操作。

If you really want to be dead simple, have your "main" CNC script read a designated directory on the file system looking for a text file that has one or more commands. 如果您真的想变得简单,请让您的“主要” CNC脚本读取文件系统上的指定目录,以查找具有一个或多个命令的文本文件。 If multiple files are there, take the earliest file and execute the command(s). 如果有多个文件,请获取最早的文件并执行命令。 Then delete the file (or move it to another directory) and get the next file. 然后删除文件(或将其移动到另一个目录)并获取下一个文件。 If there's no file, sleep for a few seconds and check again. 如果没有文件,请睡眠几秒钟,然后再次检查。 Repeat ad nauseam. 重复广告恶心。 Then your C# app just has to write a command file to the correct directory. 然后,您的C#应用​​程序只需要将命令文件写入正确的目录。

Your better bet is to combine gevent with GIPC https://gehrcke.de/gipc/ 您最好的选择是将gevent与GIPC结合使用https://gehrcke.de/gipc/

This allows for asynchronous calls to a stack, and communication between separate processes. 这允许异步调用堆栈,以及在单独的进程之间进行通信。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM