无法停止导入数据
Posted
技术标签:
【中文标题】无法停止导入数据【英文标题】:Unable to stop importing data 【发布时间】:2016-10-25 22:46:27 【问题描述】:我使用 python 编写了一个数据采集代码,现在我正在尝试使用 Qt Designer 将我的代码与 GUI 应用程序接口。我的问题是当通过单击主窗口上的 startButton 导入我的数据采集代码(sensor.py)时,程序开始收集数据,但我无法通过单击 stopButton 来停止它,甚至我无法按下任何其他按钮,我必须关闭我的主要项目以停止收集数据。
这是我的主要项目代码:
from PyQt4 import QtCore, QtGui
import sys
from mainwindow import Ui_MainWindow
from gpiodialog import Ui_GPIODialog
from savedialog import Ui_SaveDialog
class dataAcquisition(QtGui.QMainWindow, Ui_MainWindow):
def __init__(self, parent=None):
super(dataAcquisition, self).__init__(parent)
self.setupUi(self)
###################The problem is under here###################
self.startButton.clicked.connect(self.startButton_clicked)
def startButton_clicked(self):
import sensor
self.stopButton.clicked.connect(self.stopButton_clicked)
def stopButton_clicked(self):
###############################################################
self.gpioButton.clicked.connect(self.gpioButton_clicked)
self.popGPIO = gpioDialog()
def gpioButton_clicked(self):
self.popGPIO.show()
self.saveButton.clicked.connect(self.saveButton_clicked)
self.popSave = saveDialog()
def saveButton_clicked(self):
self.popSave.show()
class gpioDialog(QtGui.QDialog, Ui_GPIODialog):
def __init__(self, parent=None):
super(gpioDialog, self).__init__(parent)
flags = QtCore.Qt.Drawer | QtCore.Qt.WindowStaysOnTopHint
self.setWindowFlags(flags)
self.setupUi(self)
self.gpioOKButton.clicked.connect(self.acceptOKButtonClicked)
def acceptOKButtonClicked(self):
self.close()
class saveDialog(QtGui.QDialog, Ui_SaveDialog):
def __init__(self, parent=None):
super(saveDialog, self).__init__(parent)
flags = QtCore.Qt.Drawer | QtCore.Qt.WindowStaysOnTopHint
self.setWindowFlags(flags)
self.setupUi(self)
self.saveOKButton.clicked.connect(self.acceptOKButtonClicked)
def acceptOKButtonClicked(self):
self.close()
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
MainWindow = dataAcquisition()
MainWindow.show()
sys.exit(app.exec_())
sensor.py 代码:
#!/usr/local/bin/python
## Reading data from a photocell sensor
import RPi.GPIO as GPIO
import time
# Tell the GPIO library to use Broadcom GPIO references
GPIO.setmode(GPIO.BOARD)
#define the pin that goes to the circuit
Pin = 7
def RCtime (Pin):
measurement = 0
#Output on the pin for # Discharge capacitor
GPIO.setup(Pin, GPIO.OUT)
GPIO.output(Pin, GPIO.LOW)
time.sleep(0.0001)
GPIO.setup(Pin, GPIO.IN)
# Count loops until voltage across capacitor reads high on GPIO
while (GPIO.input(Pin) == GPIO.LOW):
measurement += 1
return measurement
# Main program loop
i = 1
while True:
file1 = open("Data%i.txt" %i ,"w")
i += 1
c = 1
while c <= 50:
print RCtime (Pin)*1.000
c += 1
file1.write(str(RCtime (Pin)))
file1.write("\n")
else:
file1.close()
我尝试使用线程并编辑我的代码,如下所示,现在我正在打印数据,但我的 GUI 应用程序没有弹出!有人知道为什么吗?
如果有人可以提供帮助,我将不胜感激。
新代码:
from PyQt4 import QtCore, QtGui
import sys
from mainwindow import Ui_MainWindow
import sensor
class dataAcquisition(QtGui.QMainWindow, Ui_MainWindow):
def __init__(self, parent=None):
super(dataAcquisition, self).__init__(parent)
self.setupUi(self)
self.threadclass = ThreadClass()
self.threadclass.start()
def Sensor(self):
val = sensor.RCtime(Pin)
class ThreadClass(QtCore.QThread):
def __init__(self, parent=None):
super(ThreadClass, self).__init__(parent)
def run(self):
val = sensor.RCtime(Pin)
print val
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
MainWindow = dataAcquisition()
MainWindow.show()
sys.exit(app.exec_())
【问题讨论】:
【参考方案1】:###################The problem is under here###################
self.startButton.clicked.connect(self.startButton_clicked)
def startButton_clicked(self):
import sensor
self.stopButton.clicked.connect(self.stopButton_clicked)
def stopButton_clicked(self):
###############################################################
你是对的。问题就在这里。
您将启动按钮回调startButton_clicked
定义为
def startButton_clicked(self):
# Data acquisition
import sensor
# Connect stop callback
self.stopButton.clicked.connect(self.stopButton_clicked)
这里的问题是数据采集脚本以无限循环结束,因此它永远不会返回,GUI 也永远不会获得控制权。
您应该在线程中使用传感器脚本,这样它就不会在运行时阻塞 GUI。
顺便说一句,请注意您可以在__init__()
时间建立所有回调连接。如果您不希望停止按钮在没有任务运行时处于活动状态,只需使用 set_enabled(False) 使其处于非活动状态。
下面是线程的样子:
从线程导入线程 导入 RPi.GPIO 作为 GPIO 进口时间
class Sensor(Thread):
def __init__(self, stop_request):
threading.Thread.__init__(self)
self.stop_request = stop_request
def run(self):
# The run method is called internally when you call Sensor.start()
# and is executed in a separate thread
# Tell the GPIO library to use Broadcom GPIO references
GPIO.setmode(GPIO.BOARD)
#define the pin that goes to the circuit
Pin = 7
def RCtime (Pin):
measurement = 0
#Output on the pin for # Discharge capacitor
GPIO.setup(Pin, GPIO.OUT)
GPIO.output(Pin, GPIO.LOW)
time.sleep(0.0001)
GPIO.setup(Pin, GPIO.IN)
# Count loops until voltage across capacitor reads high on GPIO
while (GPIO.input(Pin) == GPIO.LOW):
measurement += 1
return measurement
# Main program loop
i = 1
# Run until stop request event is set
while not self.stop_request.is_set():
# Note you can use this syntax for file handling
with open("Data%i.txt" %i ,"w") as file1:
# And you can use range to loop 50 times,
# no need to use explicit loop variable like in C
for _ in range(50):
print RCtime (Pin)*1.000
file1.write(str(RCtime (Pin)))
file1.write("\n")
i += 1
# Clear stop request event
self.stop_request.clear()
在主代码中插入Sensor
对象,如下所示:
from sensor import Sensor
from threading import Event
class dataAcquisition(QtGui.QMainWindow, Ui_MainWindow):
def __init__(self, parent=None):
super(dataAcquisition, self).__init__(parent)
self.setupUi(self)
# Initialize stop request event
self.stop_request = Event()
def startButton_clicked(self):
# Initialize thead, passing the event
self.sensor = Sensor(self.stop_request)
# Start thread
self.sensor.start()
def stopButton_clicked(self):
# Set stop_request event to ask the thread to stop
self.stop_request.set()
我让你弄清楚 GUI 部分。这是另一个故事。 (用户按下停止按钮和线程实际停止之间可能有一点时间,因此在理想情况下,您可能希望等待线程实际完成,然后再重新启用开始按钮。搜索Thread.join()
。)
此代码完全未经测试。我不是Threading
专家。我只是想通了阅读docs。
如果它不能立即起作用,它至少应该是一个好的提示。
【讨论】:
感谢杰罗姆的回答。我尝试使用线程并编辑我的代码,如“编辑问题后”所示,现在我正在打印数据,但我的 GUI 应用程序没有弹出!你知道为什么吗? 你修改了sensor.py吗?因为如果你没有,你仍然有同样的问题。导入传感器时,会执行整个 sensor.py 脚本文件。由于这发生在您的主脚本的开头,您甚至从未达到类 dataAcquisition 声明。有几种方法可以使事情正确,但基本上想法是将所有内容放入对象中以避免在导入时执行内容。我想,传感器对象可以是线程本身或专用对象。显然,这可以在主文件或单独的文件中完成。 我确实通过编辑sensor.py和我的新ThreadClass类尝试了很多,但不幸的是它没有工作!我是 python 新手,如果你能帮助我,我将不胜感激。以上是关于无法停止导入数据的主要内容,如果未能解决你的问题,请参考以下文章
python ImportError:无法从'faker'导入名称'Faker'
如何停止获取 ImportError:将 django 与 wsgi 一起使用时无法导入设置“mofin.settings”?