Search code examples
pythonimportsubprocessstorecollect

Collect data in main program, then run an external program to process collected data and use result to plot in main


I am developing a program to be the user interface that collects data and then use an external program to process it, finally, fetch the results back to plot them in main. My problem is that I cannot manage to use a proper import function without falling into a loop.

For simplicity reasons, I will create a dummy code that represents what I am doing and my problem:

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

Add.py

from main import data_a

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

Multiply.py

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

Disclaimer: There are clearly some errors in this dummy code, but I just wanted to illustrate the general flow.

The errors I am getting are:

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

or just going into an infinite loop asking for the input data

Thanks for the help!


Solution

  • In this code you have many mistakes.

    There are no data_a, data_b but self.data_a, self.data_b.

    You created class Input but you never created instances like

    data = Input(num1, num2)
    

    to keep data in this class.

    But all this is useless because self.data_a self.data_a are created dynamically in memory when you run main.py but import main can load only code from file main.py - it can't get data created when main was running. You would have to save data in file and other script would have to read from file. OR you would have to send it as argument in command line run(['python',"multiply.py", str(num1)] and other script would have to use sys.argv[1] to get it. And script has to use print() to send result back to main (subprocess). And main would have to read this string, split to separated numbers and convert to integer - so it would need a lot work.

    There is also other problem. When you import main then it runs all code in this file which is not in functions - so you have loop which ask again for inputs.

    I would do it in different way. I would put code in functions in Add.py, Multiply.py and I would import Add, Multiply in main. And this way I could run it without subprocess

    Something like this

    Add.py

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

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

    EDIT:

    With subprocess it could look like this

    Add.py

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

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