如何从python模块运行带有无限循环的多个.py文件?

时间:2018-04-16 17:52:16

标签: python-3.x tkinter executable pyserial

我有两个文件。我们称之为file_X.py和file_Y.py。两者都有无限循环,不断从COM端口读取数据。我有一个带有两个按钮的tkinter模块来启动file_X和file_Y。因此,如果我单击按钮A,我希望file_X运行,按钮B将启动file_Y。如何并行运行这些文件并让它们在各自的命令提示终端中显示数据?

我尝试使用runpy和os.system。即使两个文件的模块都能正常工作,os.system也会给我一个错误。另一方面,当第一个模块运行时,runpy不会让我点击另一个按钮。

Tkinter模块:

IPropertySourceProvider

file_X和file_Y具有几乎相同的代码,但是连接到不同的COM端口并且具有不同的字符串修改。

import tkinter as tk
import time

import runpy

root = tk.Tk()
root. title("App")
root.geometry('700x500')

v = tk.IntVar()
v.set(-1)

button_labels = [
    (" Device 1 "),
    (" Device 2 ")]

def ShowChoice():
    choice = v.get() + 1
    if(choice == 1):
        runpy.run_module('file_X', run_name='__main__')

    elif(choice == 2):
        runpy.run_module('file_Y', run_name='__main__')

tk.Label(root, 
         text="""Choose the device you want to launch:""",
         font = 'Arial 20 bold',
         justify = tk.LEFT,
         height = 6,
         padx = 20).pack()

for val, button_label in enumerate(button_labels):
    tk.Radiobutton(root,
                   text = button_label,
                   font = 'Times 12 bold',
                   indicatoron = 0,
                   bg = 'cornflower blue',
                   width = 40,
                   padx = 20,
                   pady = 5,
                   variable=v,
                   command=ShowChoice,
                   value=val).pack(anchor=tk.S)

root.mainloop()

1 个答案:

答案 0 :(得分:0)

您可以使用线程,多处理或子进程模块。

这是一个演示线程模块的快速示例。

import threading, time

def Start(name=''):
    cnt=0
    while(cnt<10):
        cnt+=1
        print "This is thread %s" % name
        time.sleep(1)

thread1 = threading.Thread(target=Start, name='Thread-1', args=('Serial1',))

thread2 = threading.Thread(target=Start, name='Thread-2', args=('Serial2',))

thread2.start()
thread1.start()


while (thread1.isAlive() and thread2.isAlive()):
    time.sleep(2)
    print "Running Threads : %s" % [thread.name for thread in threading.enumerate()]


print "done"

正如所建议的那样,您可以导入file_X和file_Y并为每个创建一个线程,使用Start()函数作为每个线程的run()方法调用的目标(可调用对象)。

import file_X, file_Y

thread1 = threading.Thread(target=file_X.Start, name='COM1') 
thread2 = threading.Thread(target=file_Y.Start, name='COM2')
thread1.start()
thread2.start()

多处理模块类似于线程。

或者使用子进程模块将file_X和file_Y作为子进程运行。

  
    
      
        

新&lt;&lt;&lt;&lt;         这是一个使用线程的解决方案。我只用一个端口进行了测试。

      
    
  
import threading
import time
import serial
import sys, os.path
import csv


def OpenSerialPort(port=""):
    print ("Open port %s" % port)

    serPort = None

    try:
        serPort = serial.Serial(port,
                    baudrate=2400,
                    bytesize=serial.EIGHTBITS,
                    parity =serial.PARITY_ODD)

    except serial.SerialException as msg:
        print( "Error opening serial port %s" % msg)

    except:
        exctype, errorMsg = sys.exc_info()[:2]
        print ("%s  %s" % (errorMsg, exctype))

    return serPort


def Reader(file_name, serialPort, stopped):
    print ("Start reading serial port %s." % serialPort.name)

    serialPort.timeout = 1.0
    while not stopped.is_set(): 
        serData = ''       
        try:                    
            #print "Reading port..."
            serData = serialPort.readline()

        except:
            exctype, errorMsg = sys.exc_info()[:2]
            print ("Error reading port - %s" % errorMsg)
            stopped.set()
            break

        if len(serData) > 0:
            serData = serData.decode('utf-8')
            serData = str(serData).replace("\r\n","")
            serData = serData.replace("\x000","")
            Log_Data(file_name, serData)
        #else:
        #    print("Reader() no Data")

    serialPort.close()
    print ("Reader finished. Closed %s" % serialPort.name)

def Init_Log(portName=''):
    #Create log file
    portName = os.path.basename(portName)
    file_name = time.strftime('%d.%m.%y__%H.%M.%S') + "__%s.csv" % portName
    with open(file_name, 'w') as f:
        csv_file = csv.writer(f)
        csv_file.writerow(['DATE','TIME','VALUE'])

    return file_name    

def Log_Data(file_name='', dataString=''):

    date_now = time.strftime('%d/%m/%y')
    time_now = time.strftime('%H:%M:%S')

    with open(file_name, 'a') as f:
        csv_file = csv.writer(f)
        csv_file.writerow([date_now, time_now, dataString])
        print([date_now, time_now, dataString])



if __name__ == "__main__":

    stopped = threading.Event() # Create stopped event to notify all threads when it is time to stop.

    #Open COM3 ports
    portName = 'COM3'
    serialPort_1 = OpenSerialPort(portName)
    if serialPort_1 == None: 
        sys.exit(1)
    file_name_1 = Init_Log(portName) #Create log file

    p1 = threading.Thread(target=Reader, args=(file_name_1, serialPort_1, stopped,))


    #Open COM4 ports
    portName = 'COM4'
    serialPort_2 = OpenSerialPort(portName)
    if serialPort_2 == None: 
        sys.exit(1)
    #Create log file
    file_name_2 = Init_Log(portName)
    p2 = threading.Thread(target=Reader, args=(file_name_2, serialPort_2, stopped,))


    #Start port reader threads
    p1.start()
    p2.start()

    #This is just a test loop that does nothing for awhile.
    loopcnt = 20
    while (loopcnt > 0) and (not stopped.is_set()):
        loopcnt -= 1
        print ("main() %d" % loopcnt)

        try:
            time.sleep(1)

        except KeyboardInterrupt: #Capture Ctrl-C
            print ("Captured Ctrl-C")
            loopcnt=0
            stopped.set()

    stopped.set()
    print ("Stopped")
    p1.join()
    p2.join()

    serialPort_1.close()
    serialPort_2.close()
    print ("Done")