Python线程class调用另一个线程class(队列帮助)
Python threaded class calls another threaded class (queue help)
我正在尝试使用 x-box 控制器控制 3 轴打印机。为了从 x-box 获取输入,我从 martinohanlon https://github.com/martinohanlon/XboxController/blob/master/XboxController.py 那里借用了代码
我还创建了逐行读取文本文件(G 代码)以移动打印机的代码。
我希望能够使用 X-Box 控制器 select 一个 G 代码文件和 运行 它,然后作为打印机 运行ning 继续监听取消按钮以防打印出错。 controller是线程化的class,我的readGcode是线程化的class.
我遇到的问题是,当我使用控制器启动 readGcode class 我无法与控制器通信,直到该线程完成。
我的临时解决方案是使用控制器 select 一个文件,然后将该文件路径传递给 readGcode class。在 readGcode class 中,它一直尝试使用 try 块打开文件并失败,直到文件路径可接受为止。然后它更改一个布尔值,使其跳过进一步阅读直到完成。
代码:
import V2_Controller as Controller
import V2_ReadFile as Read
import time
import sys
# file daialogue
import tkinter as tk
from tkinter import filedialog
# when X is selected on the x-box controller
def X(xValue):
if not bool(xValue):
try:
f=selectfile()
rf.setfilename(f)
except:
print("failed to select file")
def selectfile():
try:
root = tk.Tk() # opens tkinter
root.withdraw() # closes the tkinter window
return filedialog.askopenfilename()
except Exception:
print("no file")
# setup xbox controller
xboxCont = Controller.XboxController(controlCallBack, deadzone=30,
scale=100, invertYAxis=True)
# init the readfile class
rf = Read.Readfile()
# set the custom function for pressing X
xboxCont.setupControlCallback(xboxCont.XboxControls.X, X)
try:
# start the controller and readfile threads
xboxCont.start()
rf.start()
xboxCont.join()
rf.join()
while True:
time.sleep(1)
# Ctrl C
except KeyboardInterrupt:
print("User cancelled")
# error
except:
print("Unexpected error:", sys.exc_info()[0])
raise
finally:
# stop the controller
xboxCont.stop()
rf.stop()
V2_Readfile
# Main class for reading the script
class Readfile(threading.Thread):
# supports all variables needed to read a script
class readfile:
fileselect = True
linecount = 0
currentline = 0
commands = []
# setup readfile class
def __init__(self):
# setup threading
threading.Thread.__init__(self)
# persist values
self.running = False
self.reading = False
def setfilename(self,filename):
self.filename = filename
# called by the thread
def run(self):
self._start()
# start reading
def _start(self):
self.running = True
while self.running:
time.sleep(1)
if not self.reading:
try:
self.startread()
except:
pass
def startread(self):
try:
with open(self.filename, "r") as f: # read a local file
f1 = f.readlines()
# run through each line and extract the command from each line
linecount = 0
line = []
for x in f1:
# read each line into an array
line.append(x.split(";")[0])
linecount += 1
# Store the variables for later use
self.readfile.linecount = linecount
self.readfile.commands = line
self.reading = True
except Exception:
pass
i = 0
while i < self.readfile.linecount and self.reading:
self.readfile.currentline = i + 1
self.readline(i)
i += 1
# the following stops the code from reading again
self.reading = False
self.filename = ""
def readline(self,line):
Sort.sortline(self.readfile.commands[line])
# stops the controller
def stop(self):
self.running = False
您可以使用像 threading.Event 这样的同步原语。
为此,您需要像这样修改 Readfile
class:
from threading import Event
class Readfile(threading.Thread):
# setup readfile class
def __init__(self):
# setup threading
threading.Thread.__init__(self)
# persist values
self.running = False
self.reading = False
self.reading_file = Event() # Initialize your event here it here
def setfilename(self,filename):
self.filename = filename
self.reading_file.set() # This awakens the reader
def _start(self):
self.running = True
self.reading_file.wait() # Thread will be stopped until readfilename is called
self.startread()
另一个值得探索的同步原语是queue.Queue
。如果您想处理多个文件名,它可能会很有用。
您在问题中描述的模式称为 Busy Waiting,应尽可能避免。
我正在尝试使用 x-box 控制器控制 3 轴打印机。为了从 x-box 获取输入,我从 martinohanlon https://github.com/martinohanlon/XboxController/blob/master/XboxController.py 那里借用了代码 我还创建了逐行读取文本文件(G 代码)以移动打印机的代码。
我希望能够使用 X-Box 控制器 select 一个 G 代码文件和 运行 它,然后作为打印机 运行ning 继续监听取消按钮以防打印出错。 controller是线程化的class,我的readGcode是线程化的class.
我遇到的问题是,当我使用控制器启动 readGcode class 我无法与控制器通信,直到该线程完成。
我的临时解决方案是使用控制器 select 一个文件,然后将该文件路径传递给 readGcode class。在 readGcode class 中,它一直尝试使用 try 块打开文件并失败,直到文件路径可接受为止。然后它更改一个布尔值,使其跳过进一步阅读直到完成。
代码:
import V2_Controller as Controller
import V2_ReadFile as Read
import time
import sys
# file daialogue
import tkinter as tk
from tkinter import filedialog
# when X is selected on the x-box controller
def X(xValue):
if not bool(xValue):
try:
f=selectfile()
rf.setfilename(f)
except:
print("failed to select file")
def selectfile():
try:
root = tk.Tk() # opens tkinter
root.withdraw() # closes the tkinter window
return filedialog.askopenfilename()
except Exception:
print("no file")
# setup xbox controller
xboxCont = Controller.XboxController(controlCallBack, deadzone=30,
scale=100, invertYAxis=True)
# init the readfile class
rf = Read.Readfile()
# set the custom function for pressing X
xboxCont.setupControlCallback(xboxCont.XboxControls.X, X)
try:
# start the controller and readfile threads
xboxCont.start()
rf.start()
xboxCont.join()
rf.join()
while True:
time.sleep(1)
# Ctrl C
except KeyboardInterrupt:
print("User cancelled")
# error
except:
print("Unexpected error:", sys.exc_info()[0])
raise
finally:
# stop the controller
xboxCont.stop()
rf.stop()
V2_Readfile
# Main class for reading the script
class Readfile(threading.Thread):
# supports all variables needed to read a script
class readfile:
fileselect = True
linecount = 0
currentline = 0
commands = []
# setup readfile class
def __init__(self):
# setup threading
threading.Thread.__init__(self)
# persist values
self.running = False
self.reading = False
def setfilename(self,filename):
self.filename = filename
# called by the thread
def run(self):
self._start()
# start reading
def _start(self):
self.running = True
while self.running:
time.sleep(1)
if not self.reading:
try:
self.startread()
except:
pass
def startread(self):
try:
with open(self.filename, "r") as f: # read a local file
f1 = f.readlines()
# run through each line and extract the command from each line
linecount = 0
line = []
for x in f1:
# read each line into an array
line.append(x.split(";")[0])
linecount += 1
# Store the variables for later use
self.readfile.linecount = linecount
self.readfile.commands = line
self.reading = True
except Exception:
pass
i = 0
while i < self.readfile.linecount and self.reading:
self.readfile.currentline = i + 1
self.readline(i)
i += 1
# the following stops the code from reading again
self.reading = False
self.filename = ""
def readline(self,line):
Sort.sortline(self.readfile.commands[line])
# stops the controller
def stop(self):
self.running = False
您可以使用像 threading.Event 这样的同步原语。
为此,您需要像这样修改 Readfile
class:
from threading import Event
class Readfile(threading.Thread):
# setup readfile class
def __init__(self):
# setup threading
threading.Thread.__init__(self)
# persist values
self.running = False
self.reading = False
self.reading_file = Event() # Initialize your event here it here
def setfilename(self,filename):
self.filename = filename
self.reading_file.set() # This awakens the reader
def _start(self):
self.running = True
self.reading_file.wait() # Thread will be stopped until readfilename is called
self.startread()
另一个值得探索的同步原语是queue.Queue
。如果您想处理多个文件名,它可能会很有用。
您在问题中描述的模式称为 Busy Waiting,应尽可能避免。