나는 아주 간단하게 들리려고 노력하고 있지만 나는 모든 종류의 문제를 계속 실행 중이다. PyQt를 사용하여 여러 파일을 동시에 꼬리 수있는 GUI를 만들려고합니다. 나는 순수 파이썬에서 꼬리에 파일이꼬리 파일을 그래픽으로 PyQt로
How can I tail a log file in Python?
내가 QThread의 내부에이 코드를 사용하여 시도 방법에 대한이 답변을 보았다. 내가 겪고있는 문제는 꼬리 과정이 결코 멈추지 않는다는 것입니다. 살해되어야합니다. GUI를 닫을 때 종료해야합니다. 나는 아래이 특정 솔루션을지고있어 또 다른 문제는
QThread: Destroyed while thread is still running
및
QWaitCondition::wakeAll(): mutex lock failure:
내가 불평 꼬리 과정이 있었다 시도했습니다
QThread: Destroyed while thread is still running
Traceback (most recent call last):
File "./tailer.py", line 27, in run
self.emit(SIGNAL('newline'), line.rstrip())
RuntimeError: underlying C/C++ object has been deleted
다른 구현이다 깨진 파이프지만, 한 번 나는 stderr = PIPE를 한 번 그만 두었다. stderr을 읽지 못했기 때문에 오류가 누락 될 수 있으므로 걱정이됩니다 (차단 될 것이고 출력이 없어야하기 때문에).
오류가 발생하면이 파일을 꼬리 3 가지 파일로 시도하십시오. 나는 0.1 초의 잠자기를하는 3 개의 파일에 루프와 쓴 다른 스크립트를 썼다. GUI를 닫고 다시 시작합니다. 때로는 때때로 오류가 발생합니다.
내가 뭘 잘못하고 있는지 말해줘.
#!/usr/bin/env python
from PyQt4.QtCore import *
from PyQt4.QtGui import *
import os
from subprocess import Popen, PIPE
class Tailer(QThread):
def __init__(self, fname, parent=None):
super(Tailer, self).__init__(parent)
self.fname = fname
self.connect(self, SIGNAL('finished()'), self.cleanup)
def cleanup(self):
print 'CLEANING UP'
self.p.kill()
print 'killed'
def run(self):
command = ["tail", "-f", self.fname]
print command
self.p = Popen(command, stdout=PIPE, stderr=PIPE)
while True:
line = self.p.stdout.readline()
self.emit(SIGNAL('newline'), line.rstrip())
if not line:
print 'BREAKING'
break
def foo(self):
self.p.kill()
class TailWidget(QWidget):
def __init__(self, fnames, parent=None):
super(TailWidget, self).__init__(parent)
layout = QGridLayout()
self.threads = {}
self.browsers = {}
for i, fname in enumerate(fnames):
if not os.path.exists(fname):
print fname, "doesn't exist; creating"
p = Popen(['touch', fname], stdout=PIPE, stderr=PIPE)
out, err = p.communicate()
ret = p.wait()
assert ret == 0
t = Tailer(fname, self)
self.threads[fname] = t
b = QTextBrowser()
self.browsers[fname] = b
layout.addWidget(QLabel('Tail on %s' % fname), 0, i)
layout.addWidget(b, 1, i)
self.connect(t, SIGNAL("newline"), b.append)
t.start()
self.setLayout(layout)
def closeEvent(self, event):
for fname, t in self.threads.items():
t.foo()
if __name__ == '__main__':
import sys
app = QApplication(sys.argv)
tw = TailWidget(sys.argv[1:])
tw.show()
sys.exit(app.exec_())
해결책으로 무엇을 권하고 싶습니까? –
'closeEvent'에서 스레드가 사라질 때까지 차단하는 것이 신속하고 더러운 솔루션이지만, 이는 추한 것입니다 (이론적으로 볼 수 있듯이 UI 스레드가 비치볼을 막을 수있을만큼 충분히 차단할 수 있음). 또는'deleteLater'를 사용하여 삭제 순서를 지정하십시오. 아니면'close'를 삼켜서 다른 시그널을 추가 할 수 있습니다. (비슷하게'close'가 일어나도록합니다. 그러나'quit'을 바로 가지지 않음으로써 객체를 파괴하는 것을 멈출 수 있습니다.) 또는'newline' 신호를 간접적으로 (예를 들어., 신호를 통해 다른 객체 또는'weakref')를 호출 할 수 있으므로 주 스레드가 죽은 후에도 안전합니다. 또는'QThread.run' 대신에'moveToThread'를 사용하십시오. – abarnert
그러나 코드를 다시 보면 ... 실제로는 더 기본적인 것일 수 있습니다. 'Tailer'와'TailWidget' 모두에 무언가를 출력하는'__del__' 메쏘드를 추가 할 수 있습니까? 'TailWayget '이 아니라'Tailer'가 삭제되기 때문에 충돌 만있을 가능성이 있기 때문에,'Tailer's를 오래 유지하면 문제가 해결됩니다. – abarnert