【问题标题】:Python Timer Threading not Terminating using Desktop ShortcutPython计时器线程未使用桌面快捷方式终止
【发布时间】:2020-07-26 08:13:06
【问题描述】:

当我从终端运行以下代码并退出窗口后,使用 Ctrl+C 或 Ctrl+Z 取消脚本,脚本完全终止。 使用 Ctrl+C 我得到这个错误:

Exception ignored in: <module 'threading' from '/usr/lib/python3.6/threading.py'>
Traceback (most recent call last):
  File "/usr/lib/python3.6/threading.py", line 1294, in _shutdown
    t.join()
  File "/usr/lib/python3.6/threading.py", line 1056, in join
    self._wait_for_tstate_lock()
  File "/usr/lib/python3.6/threading.py", line 1072, in _wait_for_tstate_lock
    elif lock.acquire(block, timeout):
KeyboardInterrupt

如果我使用桌面链接:

#!/usr/bin/env xdg-open

[Desktop Entry]
Type=Application
Name=MyProblem
Exec=/home/USER/myProblem.py
Terminal=false
Name[en_CA]=myProblem

然后退出窗口,线程似乎仍在运行(通过尝试注销我的桌面并且出现通知程序显示 MyProblem 正忙)。

线程代码未终止,我了解在等待期后触发线程后,很难终止。我看过很多帖子,包括: Python threading.timer - repeat function every 'n' seconds Python threading, threads do not close

由于这是一个 threading.Timer,似乎没有使用 daemon=True 的方法。

我不确定在离开窗口之前如何在 closeEvent 中完全关闭线程。 每个人都保持安全。谢谢。

#!/usr/bin/python3
from datetime import datetime, timedelta
from PyQt5.QtWidgets import (QAction, QApplication, QCheckBox, QGridLayout, QMainWindow, QMenuBar, QWidget)
import os; import subprocess; import sys; import threading; import time
class MyProblem(QMainWindow):
    def __init__(self):
        super().__init__()
        self.initUI()
########################################
    def closeEvent(self, event):
# what do I place here - thr is a NoneType
        None
########################################
    def recordTimedAudio(self, tL, tfn):
# record audio
        self.rec_args =['arecord', '--device=hw', '-d', str(tL), '-f', 'cd', '-t', 'wav', tfn +'.wav']
        self.rec = subprocess.Popen(self.rec_args, shell=False)
########################################
    def timedRecording(self):
        dateData =['2020-04-13 13:06:00','2020-04-13 13:07:00'] # this should be changed for future dates/times
# My code uses a for loop to create a number of threads, but the end go through a series
        for d in dateData:
# Create Start Time in Seconds
            t = time.strptime(d, '%Y-%m-%d %H:%M:%S')
            t = time.mktime(t)
            thr = threading.Timer(int(t-time.time()), self.recordTimedAudio, ['10','File1']).start() #/27190809/
            print(thr) # This comes back None
            self.timerAction.setEnabled(False)
########################################
    def initUI(self):
        self.setGeometry(5,5,100,100); self.mainWidget = QWidget()
        self.layout = QGridLayout();   self.mainWidget.setLayout(self.layout)
        self.setCentralWidget(self.mainWidget)
# Menu
        self.mainMenu = self.menuBar()
        self.optionsMenu = self.mainMenu.addMenu('Options')
        self.timerAction = QAction('Set Timer', checkable=True)
        self.timerAction.triggered.connect(self.timedRecording)
        self.optionsMenu.addAction(self.timerAction)
        self.show()
########################################
if __name__ =='__main__':
    app = QApplication(sys.argv)
    ex = MyProblem()
    sys.exit(app.exec_())
################################################################################################END

【问题讨论】:

    标签: python multithreading timer pyqt


    【解决方案1】:

    我无法让线程停止,对于这样的时间问题,线程可能是多余的。我创建了一个解决方法,将来可能会对某人有所帮助。用这些例程替换上面的代码:

    def timedRecording(self):
        dateData =['2020-04-13 13:06:00','2020-04-13 13:07:00'] # this should be changed for future dates/times
        for d in dateData:
    # Create Start Time in Seconds
            t = time.strptime(d, '%Y-%m-%d %H:%M:%S')
            t = time.mktime(t)
            self.timerData.append([t, trecLength, urlText, tfilename]) # start time recording length, url, filename
        self.timerData.sort(key = lambda x: x[0]) # /4174941/
        self.treclen = len(self.timerData)
        if self.treclen>0:
            self.rtime.setText('Timer Set')
            self.timerAction.setEnabled(False)
            self.startTRecTimer()
    ########################################
    def recordTimedAudio(self, tL, urlText, tfn):
        self.rec_args =['arecord', '--device=hw', '-d', str(tL), '-f', 'cd', '-t', 'wav', os.path.join(os.path.sep,self.audioDir, tfn +'.wav')]
        self.rec = subprocess.Popen(self.rec_args, shell=False) #https://docs.python.org/2/library/subprocess.html#popen-constructor
    # Learning a trick from: https://stackoverflow.com/questions/27190809/
        if self.trecNum < self.treclen-1:
            self.trecNum+=1
            self.startTRecTimer()
    ########################################
    def startTRecTimer(self):
        if time.time() < self.timerData[self.trecNum][0]: # time has not elapsed /415511/
    # Start QTimer delay then Start Recording
            delayTime = int(self.timerData[self.trecNum][0]-time.time())*1000 # QTimer uses milliseconds
            self.trecTimer = QTimer()
            self.trecTimer.setSingleShot(True)
            self.trecTimer.timeout.connect(lambda: self.recordTimedAudio(self.timerData[self.trecNum][1], self.timerData[self.trecNum][2], self.timerData[self.trecNum][3]))
            self.trecTimer.start(delayTime)
    

    同时添加到 initUI:

    self.rec = None
    

    到窗口的closeEvent:

            if self.rec != None:
                self.rec.terminate() # /16866602/
    

    所以子进程停止了。

    【讨论】:

      猜你喜欢
      • 2016-07-18
      • 1970-01-01
      • 2013-03-14
      • 1970-01-01
      • 2012-08-05
      • 1970-01-01
      • 2022-10-19
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多