简体   繁体   English

每次另一个进程更新文件时如何从文件中读取

[英]How to read from a file each time another another process updates it

I am working on my first application.我正在处理我的第一个应用程序。 In one window, I have a button that, when clicked, I want to execute a method from another module.在一个窗口中,我有一个按钮,单击该按钮后,我想从另一个模块执行一个方法。 This method takes an indeterminate amount of time to execute and depends on user input in the terminal.此方法需要不确定的时间来执行,并且取决于终端中的用户输入。 This method creates a file and repeatedly opens it, writes things to the file, and closes the file.此方法创建一个文件并重复打开它,将内容写入文件,然后关闭文件。 At the same time this is running I have a matplotlib graph widget in the window with a plot that I want to update each time something new is written to the file by reading and plotting data from the most recent line of the file.在运行的同时,我在窗口中有一个 matplotlib 图形小部件,其中包含一个绘图,每次通过读取和绘制文件最新行中的数据将新内容写入文件时,我都想更新该绘图。

As I understand it, nothing in my application will respond until the user input function finishes if I have it running in the main thread of my QT program.据我了解,如果我在 QT 程序的主线程中运行它,则在用户输入函数完成之前,我的应用程序中的任何内容都不会响应。 To address this I tried moving the execution of the user input method into a worker thread.为了解决这个问题,我尝试将用户输入法的执行移到工作线程中。 In the way I have done this I'm not convinced it is working.以我这样做的方式,我不相信它正在起作用。 As a test I tried making a QTimer that tried to read the file and plot it every second (with some added stuff to check if the file exists).作为测试,我尝试制作一个 QTimer,它尝试读取文件并每秒绘制一次(添加一些内容来检查文件是否存在)。 This prints that the file doesn't exist yet right until the long task, and then does nothing, until the long task is done and then starts reading and plotting the file every second.这将打印文件在长任务之前还不存在,然后什么都不做,直到长任务完成然后开始每秒读取和绘制文件。 I'm not sure if this means I'm not doing the threading properly or if something else is going on.我不确定这是否意味着我没有正确地进行线程处理,或者是否正在发生其他事情。

To check for changes to the file, I've tried using QFileSystemWatcher.为了检查文件的更改,我尝试使用 QFileSystemWatcher。 UPDATE: Right now, nothing happens while the userInputFunction() is running, but when it finishes I get "data/runName_Rec.txt dataFileCreated".更新:现在,当 userInputFunction() 运行时什么也没有发生,但是当它完成时我得到“data/runName_Rec.txt dataFileCreated”。 If I then manually edit the file in any way the plotting happens as it should.如果我然后以任何方式手动编辑文件,绘图就会发生。 But I still want to thread it correctly so that the watcher works while I'm running userInputFunction()但我仍然想正确地将其线程化,以便在我运行 userInputFunction() 时观察者工作

Here is a simplified sample of the relevant parts of my code.这是我的代码相关部分的简化示例。 Sorry for any bad style issues.对于任何糟糕的风格问题,我们深表歉意。

from PyQt5 import QtWidgets, uic, QtCore, QtGui
from pyqtgraph import PlotWidget
from PyQt5.QtCore import QObject, QThread, pyqtSignal
import pyqtgraph as pg
import sys
from PyQt5.QtWidgets import QApplication, QWidget, QInputDialog, QLineEdit, QFileDialog, QMainWindow
import os
from os.path import exists
import csv
import numpy as np
import pandas as pd

import myModule

dirname = os.path.dirname(__file__)
class Worker(QObject):
    finished = pyqtSignal()

    def run(self,param1,param2):
        """Long-running task with user input from terminal."""
        myModule.userInputFunction(param1,param2)
        self.finished.emit()

class someWindow(QtWidgets.QMainWindow):

    def __init__(self, *args, **kwargs):
        super(someWindow, self).__init__(*args, **kwargs)

        #Load the UI Page
        uic.loadUi('somewindow.ui', self)

        self.directoryPath = "data"

        self.fs_watcher = QtCore.QFileSystemWatcher()

        self.fs_watcher.addPath(self.directoryPath)
        self.fs_watcher.directoryChanged.connect(self.dataFileCreated)
        
        self.StartScanButton.clicked.connect(self.startSliceScan)
        self.EndScanButton.clicked.connect(self.endScan)

    def dataFileCreated(self):
        self.filePath = os.path.join(dirname, "data/"+ self.runNameBox.toPlainText()+"_Rec.txt")
        print(self.filePath + " dataFileCreated")
        self.fs_watcher.addPath(self.filePath)
        self.fs_watcher.fileChanged.connect(self.update_graph)

    def update_graph(self):
        if exists(self.path):
            print("file exists!")
            #then read the filePath.txt and plots the data
    else:
        print("file doesn't exist yet")

    def endScan(self):
        #change some display things

    def runLongTask(self):
        # Step 2: Create a QThread object
        self.thread = QThread()
        # Step 3: Create a worker object
        self.worker = Worker()
        # Step 4: Move worker to the thread
        self.worker.moveToThread(self.thread)
        # Step 5: Connect signals and slots
        self.thread.started.connect(self.worker.run(param1,param2))
        self.worker.finished.connect(self.thread.quit)
        self.worker.finished.connect(self.worker.deleteLater)
        self.thread.finished.connect(self.thread.deleteLater)
        # Step 6: Start the thread
        self.thread.start()

if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)
    w = someWindow()
    w.show()
    sys.exit(app.exec_())

As you explained, when your program starts, the file in question does not exist yet.正如您所解释的,当您的程序启动时,相关文件尚不存在。

From the documentation of QFileSystemWatcher :QFileSystemWatcher文档中

Adds path to the file system watcher if path exists.如果路径存在,则将路径添加到文件系统观察程序。 The path is not added if it does not exist, or if it is already being monitored by the file system watcher.如果该路径不存在,或者文件系统观察程序已对其进行监视,则不会添加该路径。

The solution to your problem is two-fold:解决您的问题有两个方面:

  1. To get notified of a newly created file, add the parent directory (ie, the directory where you expect the file to appear) to your watcher (in your case, simply '.').要获得新创建文件的通知,请将父目录(即您希望文件出现的目录)添加到您的观察者(在您的情况下,只需'.')。 You will then get a notification (thedirectoryChanged signal ) when any new files are created.然后,当创建任何新文件时,您将收到通知(directoryChanged 信号)。 Your update_graph method is already prepared for this dynamic as it checks for existence of your target file;您的update_graph方法已经为此动态做好了准备,因为它会检查您的目标文件是否存在; so you can directly connect it to directoryChanged as you did with fileChanged .因此您可以像使用fileChanged一样将其直接连接到directoryChanged
  2. As soon as the file is there, to get notified of any future changes to the file, add the file itself to the watcher like you already did, but this time also do it in update_graph (it may appear redundant, but note, as in the quote above, redundantly adding a file is not a problem; also when you add the path at start you cover the case where the file is already there).只要文件在那里,为了获得文件未来任何更改的通知,将文件本身添加到观察者就像你已经做的那样,但这次也在update_graph做(它可能看起来多余,但请注意,如上面的引用,多余地添加文件不是问题;同样,当您在开始时添加路径时,您涵盖了文件已经存在的情况)。
  3. In case the file is deleted, you will get the directoryChanged event again.如果文件被删除,您将再次收到directoryChanged事件。 You do not need to remove the path of the deleted file.您不需要删除已删除文件的路径。
  4. Finally, note that addPath() returns bool success.最后,请注意addPath()返回 bool 成功。 So you should check the return value in your program.所以你应该检查程序中的返回值。

The reason for this behavior is that when you call addPath() , the file or directory found at that path is directly added to the watcher (not the path pointing to it).这种行为的原因是当您调用addPath() ,在该路径找到的文件或目录会直接添加到观察者(而不是指向它的路径)。 So the notification only works during a file's (or directory's) lifetime.因此,通知仅在文件(或目录)的生命周期内有效。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 Python:如何从另一个进程读取变量? - Python: how to read variables from another process? 从另一个进程正在使用的文件中读取 - Read from a file which is being used by another process C#:从另一个进程正在使用的文件中快速读取 - C#: Read fast from a file that is being used by another process Python 3-如何创建一个变量,每当另一个变量更新时,该变量将成为一个新变量 - Python 3 - How to create an variable that will become a new variable each time another variable updates Python:如何从另一个进程读取stdout非阻塞? - Python: How to read stdout non blocking from another process? 如何在另一个进程的原子事务期间读取修改后的表? - How to read a modified table during an atomic transaction from another process? 如何从每一行文本中读取特定字符并将其写到另一个文件中? - How do I read in specific characters from each line of text and write it out to another file? 如何从 stream 读取 CSV 文件并在写入时处理每一行? - How to read a CSV file from a stream and process each line as it is written? 为另一个文件中的每一行快速处理一个文件的每一行 - Fast process each line of one file for each line in another file 相对于文本文件中另一列中的另一个值,逐个读取列中的每个值 - Read each value one by one in a column with respect to another values in another column from a text file
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM