无法停止导入数据

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 新手,如果你能帮助我,我将不胜感激。

以上是关于无法停止导入数据的主要内容,如果未能解决你的问题,请参考以下文章

navicat导入数据到一定量就停止了

强制excel停止对csv导入数据应用“自动更正”[关闭]

python ImportError:无法从'faker'导入名称'Faker'

如何停止获取 ImportError:将 django 与 wsgi 一起使用时无法导入设置“mofin.settings”?

如何远程把sql server中的数据导入到本地sql server中?

SQL Server2014 任务导入数据导入Excel表操作无法完成