在主程序中收集数据,然后运行外部程序来处理收集的数据并使用结果在主程序中绘图

Posted

技术标签:

【中文标题】在主程序中收集数据,然后运行外部程序来处理收集的数据并使用结果在主程序中绘图【英文标题】:Collect data in main program, then run an external program to process collected data and use result to plot in main 【发布时间】:2021-12-04 14:51:48 【问题描述】:

我正在开发一个程序作为收集数据的用户界面,然后使用外部程序对其进行处理,最后,将结果取回并在 main 中绘制它们。 我的问题是我无法在不陷入循环的情况下使用正确的导入功能。

为简单起见,我将创建一个虚拟代码来代表我正在做的事情和我的问题:

main.py

import sys,os, math, statistics, re
from multiprocessing import Process,Queue,Pipe
import subprocess

'''---Data input block---'''

print('-----Welcome to mainX-----')
num1=int(input('type number 1:'))
num2=int(input('type number 2:'))

print('choose a tool between adding and multiplying')
tool=input('multiply/add: ')

'''---Data storage block---'''

class Input:

    def __init__(self, point_a, point_b):
        self.data_a=num1
        self.data_b=num2

    def data_a(self):
        return(self.data_a)

    def data_b(self):
        return(self.data_b)

'''---external program block---'''

if tool == 'add':
     Add= subprocess.run(['python',"add.py"], capture_output=True)

if tool == 'multiply':
     Multiply= subprocess.run(['python',"multiply.py"], capture_output=True)

'''---Plotting block---'''

fig = plt.figure(figsize = (7,5))
ax= fig.add_subplot(111)

TK = np.linspace(1,10)

if tool == add:
   ax.plot(TK, addresult, label='This is te result of addition', c='g', linewidth=3)

if tool == multiply:
       ax.plot(TK, multiplyresult, label='This is te result of multiplying', c='g', linewidth=3)



ax.set_xlim(270, 400)
plt.legend(fontsize=14)
plt.tight_layout()
plt.show()

添加.py

from main import data_a

addresult:[data_a +1, data_a +2, data_a +3]

乘法.py

from main import data_b
multiplyresult: [data_b *1, data_b *2, data_b *3]

免责声明:这个虚拟代码显然存在一些错误,但我只是想说明一般流程。

我得到的错误是:

ImportError: cannot import name 'data_a' from 'main'

或者只是进入一个无限循环询问输入数据

感谢您的帮助!

【问题讨论】:

总是将完整的错误消息(从单词“Traceback”开始)作为文本(不是截图,不是链接到外部门户)有问题(不是评论)。还有其他有用的信息。 main.py 中没有data_a - 在Input 类中只有self.data_a 但它对你没用。您不能运行当前运行程序中创建的其他脚本和import 数据。 import 仅从文件 main 加载代码,但无法获取运行程序在内存中创建的数据。您必须将数据保存在文件中并从其他脚本中的文件中读取。或者您应该将Add 导入main 并直接运行函数 - 然后您可以直接使用数据。 在类中定义 def data_a(...) 时,它会创建变量 self.data_a 以在其他函数中访问此函数 - 但您也使用 self.data_a 来保持值 self.data_a=num1 因此其中一个变量可以被删除。 您应该将代码保留在函数中,因为当您 import main 时,它会运行不在函数内部的代码。 你定义了类Input,但你从未使用过它。 【参考方案1】:

在这段代码中你有很多错误。

没有data_adata_b,但有self.data_aself.data_b

您创建了类 Input,但您从未创建过类似的实例

data = Input(num1, num2)

将数据保存在此类中。

但这一切都没有用,因为self.data_a self.data_a 是在您运行main.py 时在内存中动态创建的,但import main 只能从文件main.py 加载代码 - 它无法获取@987654332 时创建的数据@ 正在运行。您必须将数据保存在文件中,而其他脚本必须从文件中读取。或者,您必须在命令行run(['python',"multiply.py", str(num1)] 中将其作为参数发送,而其他脚本必须使用sys.argv[1] 来获取它。并且脚本必须使用print() 将结果发送回main (subprocess)。而main 必须读取这个字符串,拆分为单独的数字并转换为整数 - 所以需要做很多工作。

还有其他问题。当您导入 main 时,它会运行此文件中不在函数中的所有代码 - 因此您有循环再次询问输入。

我会以不同的方式来做。我会将代码放入Add.pyMultiply.py 的函数中,我会将import Add, Multiply 放入main 中。这样我就可以在没有subprocess的情况下运行它

类似的东西

添加.py

def add(data):
    return [data+1, data+2, data+3]

乘法.py

def multiply(data)
    return [data*1, data*2, data*3]

main.py

import sys  # PEP8: imports in separated lines
import os
import math
import statistics
import re

from Add import add
from Multiply import multiply

# --- classes ---

class Input:

    def __init__(self, a, b):
        self.a = a
        self.a = b

    def get_a(self):
        return self.a

    def get_b(self):
        return self.b

# --- functions ---

def main():
    # ---Data input block---
    
    print('-----Welcome to mainX-----')
    num1 = int(input('type number 1:'))  # PEP8: spaces aroung `=`
    num2 = int(input('type number 2:'))
    
    print('choose a tool between adding and multiplying')
    tool = input('multiply/add: ')
    
    # ---Data storage block---
    
    data = Input(num1, num2)
    
    # ---external program block---
    
    if tool == 'add':
         result = add(data.get_a())
    
    if tool == 'multiply':
         result = multiply(data.get_b())
    
    # ---Plotting block---
    
    fig = plt.figure(figsize=(7,5))  
    ax = fig.add_subplot(111)
    
    TK = np.linspace(1,10)
    
    if tool == 'add':
        ax.plot(TK, result, label='This is te result of addition', c='g', linewidth=3)
    
    if tool == 'multiply':
        ax.plot(TK, result, label='This is te result of multiplying', c='g', linewidth=3)
    
    ax.set_xlim(270, 400)
    plt.legend(fontsize=14)
    plt.tight_layout()
    plt.show()
    
if __name__ == '__main__':
    main()

编辑:

subprocess 可能看起来像这样

添加.py

import sys

if len(sys.argv) > 1
    data = int(sys.argv[1])
    print(data+1, data+2, data+3)

乘法.py

import sys

if len(sys.argv) > 1
    data = int(sys.argv[1])
    print(data*1, data*2, data*3)

main.py

import sys  # PEP8: imports in separated lines
import os
import math
import statistics
import re
import subprocess

# --- classes ---

class Input:

    def __init__(self, a, b):
        self.a = a
        self.a = b

    def get_a(self):
        return self.a

    def get_b(self):
        return self.b

# --- functions ---

def main():
    # ---Data input block---
    
    print('-----Welcome to mainX-----')
    num1 = int(input('type number 1:'))  # PEP8: spaces aroung `=`
    num2 = int(input('type number 2:'))
    
    print('choose a tool between adding and multiplying')
    tool = input('multiply/add: ')
    
    # ---Data storage block---
    
    data = Input(num1, num2)
    
    # ---external program block---
    
    if tool == 'add':
         p = subprocess.run(['python', 'Add.py', str(data.get_a())])
    
    if tool == 'multiply':
         p = subprocess.run(['python', 'Multiply.py', str(data.get_b())])
    
    output = p.stdout
    result = [int(value) for value in output.split(' ')]

    # ---Plotting block---
    
    fig = plt.figure(figsize=(7,5))  
    ax = fig.add_subplot(111)
    
    TK = np.linspace(1,10)
    
    if tool == 'add':
        ax.plot(TK, result, label='This is te result of addition', c='g', linewidth=3)
    
    if tool == 'multiply':
        ax.plot(TK, result, label='This is te result of multiplying', c='g', linewidth=3)
    
    ax.set_xlim(270, 400)
    plt.legend(fontsize=14)
    plt.tight_layout()
    plt.show()
    
if __name__ == '__main__':
    main()

【讨论】:

非常感谢您的帮助。这正是我一直在寻找的,但不知道细节。出于某种原因,我无法运行子进程版本,但第一种方法效果很好。我刚刚修复了一些我将要发布的细节,以防有人想使用它。非常感谢!【参考方案2】:

正如@furas 所建议的那样,完成这项工作的最佳方法是将输入保存在 main 中,在外部脚本中定义方法,然后将它们导入 main 以与输入一起使用信息。 您也可以将结果保存在 main 中,然后将其用于您想要的任何内容。像绘图一样。

为了补充@furas 编写的代码并使其功能齐全,我做了一些小的调整:

Add.py

def add(data):
    return [data+1, data+2, data+3]

Multiply.py

def multiply(data):
    return [data*1, data*2, data*3]

ma​​in.py

import sys  # PEP8: imports in separated lines
import os
import math
import statistics
import re
import numpy as np
import matplotlib.pyplot as plt


from Add import add
from Multiply import multiply


# --- classes ---

class Input:

    def __init__(self, a, b):
        self.a = a
        self.b = b

    def get_a(self):
        return self.a

    def get_b(self):
        return self.b

# --- functions ---

def main():
    # ---Data input block---

    print('-----Welcome to mainX-----')
    num1 = int(input('type number 1:'))  # PEP8: spaces aroung `=`
    num2 = int(input('type number 2:'))

    print('choose a tool between adding and multiplying')
    tool = input('multiply/add: ')

    # ---Data storage block---

    data = Input(num1, num2)

    # ---external program block---

    if tool == 'add':
         result = add(data.get_a())

    if tool == 'multiply':
         result = multiply(data.get_b())

    # ---Plotting block---

    fig = plt.figure(figsize=(7,5))
    ax = fig.add_subplot(111)

    if tool == 'add':
        ax.plot(result, label='This is the result of addition', c='r', linewidth=3)

    if tool == 'multiply':
        ax.plot(result, label='This is the result of multiplying', c='g', linewidth=3)

    plt.legend(fontsize=14)
    plt.tight_layout()
    plt.show()

if __name__ == '__main__':
    main()

【讨论】:

以上是关于在主程序中收集数据,然后运行外部程序来处理收集的数据并使用结果在主程序中绘图的主要内容,如果未能解决你的问题,请参考以下文章

Flume分布式日志收集系统

在 Python 中收集和报告多个异常的惯用方式

如何在 PyQt4 中使用 QtGui 来收集 Python 程序的输入变量?

从正在运行的程序中收集数据

使用完成处理程序按顺序执行操作

GC算法