Làm cách nào để xem tệp thay đổi?


323

Tôi có một tệp nhật ký được viết bởi một quy trình khác mà tôi muốn xem các thay đổi. Mỗi khi có thay đổi, tôi muốn đọc dữ liệu mới để xử lý dữ liệu đó.

Cách tốt nhất để làm điều này là gì? Tôi đã hy vọng sẽ có một số loại hook từ thư viện PyWin32. Tôi đã tìm thấy win32file.FindNextChangeNotificationchức năng nhưng không biết làm thế nào để yêu cầu nó xem một tệp cụ thể.

Nếu bất cứ ai làm bất cứ điều gì như thế này, tôi thực sự rất biết ơn khi nghe ...

[Chỉnh sửa] Tôi nên đề cập rằng tôi đã theo đuổi một giải pháp không yêu cầu bỏ phiếu.

[Chỉnh sửa] Nguyền rủa! Có vẻ như điều này không hoạt động trên một ổ đĩa mạng được ánh xạ. Tôi đoán các cửa sổ không 'nghe' bất kỳ cập nhật nào cho tệp theo cách nó thực hiện trên một đĩa cục bộ.


1
trên Linux người ta có thể sử dụng stracecác writecuộc gọi giám sát cho việc này
test30

Câu trả lời của @ simao sử dụng python-watchdog. Python-Watchdog có tài liệu tuyệt vời -> đây là một liên kết đến tài liệu ["QuickStart"] cung cấp một ví dụ mã tối thiểu theo dõi thư mục làm việc hiện tại.
Trevor Boyd Smith

Câu trả lời:


79

Bạn đã xem tài liệu có sẵn trên http://timgolden.me.uk/python/win32_how_do_i/watch_directory_for_changes.html ? Nếu bạn chỉ cần nó hoạt động trong Windows, ví dụ thứ 2 dường như chính xác là những gì bạn muốn (nếu bạn trao đổi đường dẫn của thư mục với một trong các tệp bạn muốn xem).

Nếu không, bỏ phiếu có thể sẽ là lựa chọn thực sự độc lập với nền tảng.

Lưu ý: Tôi chưa thử bất kỳ giải pháp nào trong số này.


5
Câu trả lời này là dành riêng cho Windows, nhưng có vẻ như một số giải pháp đa nền tảng cho vấn đề này cũng đã được đăng ở đây.
Anderson Green

Có một điểm chuẩn, nếu quá trình này chậm hơn thì thực hiện nó bằng ngôn ngữ bản địa như c ++?
dùng1767754

Tốt hơn là chèn nội dung có liên quan từ các nguồn được trích dẫn vì chúng có thể trở nên lỗi thời.
Trilarion

2
(1.) ở cuối câu trả lời này là một sự từ chối mạnh mẽ ... "Tôi chưa thử bất kỳ giải pháp nào trong số này". (2.) câu trả lời này ít nhiều là câu trả lời "chỉ liên kết" (3.) câu trả lời đề cập đến "bỏ phiếu" nhưng không cung cấp thêm bất cứ điều gì hữu ích sau đó ... trong đó câu trả lời của @ Deestan cung cấp một số thông tin tốt về bỏ phiếu
Trevor Boyd Smith

283

Bạn đã thử sử dụng Watchdog chưa?

Thư viện API Python và các tiện ích shell để theo dõi các sự kiện hệ thống tệp.

Giám sát thư mục được thực hiện dễ dàng với

  • API đa nền tảng.
  • Một công cụ shell để chạy các lệnh để đáp ứng với thay đổi thư mục.

Bắt đầu nhanh chóng với một ví dụ đơn giản trong Quickstart ...


56
Có thể cài đặt với easy_install? Kiểm tra. Giấy phép miễn phí? Kiểm tra . Giải quyết vấn đề trên các nền tảng lớn? Kiểm tra . Tôi tán thành câu trả lời này. Chỉ lưu ý: ví dụ trên trang dự án của họ không hoạt động. Sử dụng một trong github của họ thay thế.
Inaimathi

6
Chúng tôi sử dụng cơ quan giám sát. Chúng tôi có thể chuyển sang QFileSystemWatcher. Chỉ cần một cảnh báo công bằng - cơ quan giám sát là tốt nhưng không hoàn hảo trên tất cả các nền tảng (tại thời điểm này). Mỗi hệ điều hành có những đặc điểm riêng. Vì vậy, trừ khi bạn tận tâm để làm cho nó hoàn hảo, bạn sẽ kéo tóc ra. Nếu bạn chỉ muốn xem 10 tệp hoặc hơn, tôi sẽ thăm dò ý kiến. Bộ nhớ đệm đĩa hệ điều hành rất trưởng thành và Watchdog liên quan đến các API bỏ phiếu dù sao đi nữa. Nó chủ yếu để xem cấu trúc thư mục khổng lồ IMHO.
SilentSteel

3
Điều tôi thích với watchdog là nó có nhiều phụ thuộc. Tất nhiên ít hơn PyQt, nhưng nó không hoạt động và cảm thấy giống như giải pháp tối thiểu, tốt nhất, thực hiện một công việc và một việc làm đúng.
AndreasT

1
@Denfromufa có đúng ở đây không? Có watchdog thực sự khóa các tập tin, vì vậy chúng không thể được chỉnh sửa đồng thời để watchdog xem chúng? Tôi khó có thể tin rằng, nó sẽ hoàn toàn vô dụng.
Michel Müller

1
@ MichelMüller Tôi chỉ kiểm tra ví dụ này (xem liên kết bên dưới) và nó hoạt động! không chắc chắn những gì đã sai trước đây, nhưng câu trả lời này không cung cấp bất kỳ ví dụ nào. stackoverflow.com/a/18599427/2230844
denfromufa

92

Nếu bỏ phiếu là đủ tốt cho bạn, tôi chỉ cần xem liệu chỉ số tệp "thời gian đã sửa đổi" thay đổi. Để đọc nó:

os.stat(filename).st_mtime

(Cũng lưu ý rằng giải pháp sự kiện thay đổi gốc của Windows không hoạt động trong mọi trường hợp, ví dụ như trên các ổ đĩa mạng.)

import os

class Monkey(object):
    def __init__(self):
        self._cached_stamp = 0
        self.filename = '/path/to/file'

    def ook(self):
        stamp = os.stat(self.filename).st_mtime
        if stamp != self._cached_stamp:
            self._cached_stamp = stamp
            # File has changed, so do something...

1
Làm thế nào bạn có thể làm điều này trên một khoảng?
dopatraman

1
@dopatraman Đây là cách bạn có thể thực hiện việc này trong một khoảng thời gian `import sys import time pub = Monkey () trong khi True: try: time.s ngủ (1) pub.watch () ngoại trừ KeyboardInterrupt: print ('\ nDone') ngoại trừ : print (lỗi chưa được xử lý: {sys.exc_info () [0]} ') `
Vlad Bezden

Giải pháp đơn giản tuyệt vời! Tôi đã thêm một kiểm tra để giữ cho nó không báo cáo tệp đã thay đổi trong lần chạy đầu tiên : if self._cached_stamp is not None.
Noumenon

50

Nếu bạn muốn một giải pháp đa nền tảng, thì hãy kiểm tra QFileSystemWatcher . Đây là một mã ví dụ (không được khử trùng):

from PyQt4 import QtCore

@QtCore.pyqtSlot(str)
def directory_changed(path):
    print('Directory Changed!!!')

@QtCore.pyqtSlot(str)
def file_changed(path):
    print('File Changed!!!')

fs_watcher = QtCore.QFileSystemWatcher(['/path/to/files_1', '/path/to/files_2', '/path/to/files_3'])

fs_watcher.connect(fs_watcher, QtCore.SIGNAL('directoryChanged(QString)'), directory_changed)
fs_watcher.connect(fs_watcher, QtCore.SIGNAL('fileChanged(QString)'), file_changed)

6
Tôi nghĩ rằng đây hoàn toàn có thể là câu trả lời hay nhất trong số các câu hỏi cho rằng họ a) dựa vào đối tượng FileSystemwatcher của Win32 và không thể chuyển hoặc thăm dò ý kiến ​​cho tệp (không tốt cho hiệu suất và sẽ không mở rộng quy mô). Thật đáng tiếc Python không có cơ sở này được xây dựng vì PyQt là một sự phụ thuộc rất lớn nếu tất cả những gì bạn đang sử dụng là lớp QFileSystemWatcher.
CadentOrange

4
Tôi thích giải pháp này. Tôi muốn chỉ ra rằng bạn sẽ cần một phiên bản QApplication để nó hoạt động, tôi đã thêm "app = QtGui.QApplication (sys.argv)" ngay dưới phần nhập và sau đó là "app.exec_ ()" sau khi kết nối tín hiệu.
spencewah

Chỉ cần thử nghiệm điều này trên một hộp Linux, tôi thấy rằng phương thức thư mục_changed đang được gọi, nhưng không phải là file_changed.
Ken Kinder

@CadentOrange, nếu bạn không thích phụ thuộc pyQT, các watchdoggói là câu trả lời đúng
Mike Pennington

tại sao không sử dụng PySidecho điều đó thay vì PyQtsử dụng nhỏ như vậy.
Ciasto piekarz

29

Nó không hoạt động trên windows (có thể với cygwin?), Nhưng đối với người dùng unix, bạn nên sử dụng lệnh gọi hệ thống "fcntl". Đây là một ví dụ trong Python. Nó chủ yếu là cùng một mã nếu bạn cần viết nó bằng C (cùng tên hàm)

import time
import fcntl
import os
import signal

FNAME = "/HOME/TOTO/FILETOWATCH"

def handler(signum, frame):
    print "File %s modified" % (FNAME,)

signal.signal(signal.SIGIO, handler)
fd = os.open(FNAME,  os.O_RDONLY)
fcntl.fcntl(fd, fcntl.F_SETSIG, 0)
fcntl.fcntl(fd, fcntl.F_NOTIFY,
            fcntl.DN_MODIFY | fcntl.DN_CREATE | fcntl.DN_MULTISHOT)

while True:
    time.sleep(10000)

3
Hoạt động như một cơ duyên với nhân Linux 2.6.31 trên hệ thống tệp ext4 (trên Ubuntu 10.04), mặc dù chỉ dành cho các thư mục - nó làm tăng IOError "không phải là thư mục" nếu tôi sử dụng nó với tệp.
David Underhill

1
TUYỆT QUÁ! Tương tự đối với tôi, chỉ hoạt động cho thư mục và xem các tập tin trong thư mục này. Nhưng nó sẽ không hoạt động đối với các tệp được sửa đổi trong các thư mục con, vì vậy có vẻ như bạn cần phải đi qua các thư mục con và xem tất cả chúng. (hoặc có cách nào tốt hơn để làm điều này?)
lfagundes

20

Kiểm tra pyinotify .

inotify thay thế dnotify (từ một câu trả lời trước đó) trong các bản linux mới hơn và cho phép theo dõi cấp độ tệp thay vì theo dõi cấp thư mục.


5
Không đặt một bộ giảm xóc vào câu trả lời này, nhưng sau khi đọc bài viết này, tôi sẽ nói rằng nó có thể không phải là một giải pháp hào nhoáng như suy nghĩ. serpentine.com/blog/2008/01/04/why-you-should-not-use-pyinotify
NuclePeon

1
pyinotify có rất nhiều nhược điểm bắt đầu từ cơ sở mã rất unpythonic đến tiêu thụ bộ nhớ. Tốt hơn để tìm kiếm các tùy chọn khác ..
Tyto

13

Chà, sau một chút hack kịch bản của Tim Golden, tôi có những thứ sau đây có vẻ hoạt động khá tốt:

import os

import win32file
import win32con

path_to_watch = "." # look at the current directory
file_to_watch = "test.txt" # look for changes to a file called test.txt

def ProcessNewData( newData ):
    print "Text added: %s"%newData

# Set up the bits we'll need for output
ACTIONS = {
  1 : "Created",
  2 : "Deleted",
  3 : "Updated",
  4 : "Renamed from something",
  5 : "Renamed to something"
}
FILE_LIST_DIRECTORY = 0x0001
hDir = win32file.CreateFile (
  path_to_watch,
  FILE_LIST_DIRECTORY,
  win32con.FILE_SHARE_READ | win32con.FILE_SHARE_WRITE,
  None,
  win32con.OPEN_EXISTING,
  win32con.FILE_FLAG_BACKUP_SEMANTICS,
  None
)

# Open the file we're interested in
a = open(file_to_watch, "r")

# Throw away any exising log data
a.read()

# Wait for new data and call ProcessNewData for each new chunk that's written
while 1:
  # Wait for a change to occur
  results = win32file.ReadDirectoryChangesW (
    hDir,
    1024,
    False,
    win32con.FILE_NOTIFY_CHANGE_LAST_WRITE,
    None,
    None
  )

  # For each change, check to see if it's updating the file we're interested in
  for action, file in results:
    full_filename = os.path.join (path_to_watch, file)
    #print file, ACTIONS.get (action, "Unknown")
    if file == file_to_watch:
        newText = a.read()
        if newText != "":
            ProcessNewData( newText )

Nó có thể có thể thực hiện với việc kiểm tra lỗi nhiều hơn, nhưng chỉ cần xem tệp nhật ký và thực hiện một số xử lý trên đó trước khi đưa nó ra màn hình, điều này hoạt động tốt.

Cảm ơn tất cả mọi người cho đầu vào của bạn - công cụ tuyệt vời!


10

Để xem một tệp duy nhất với bỏ phiếu và phụ thuộc tối thiểu, đây là một ví dụ hoàn chỉnh, dựa trên câu trả lời từ Deestan (ở trên):

import os
import sys 
import time

class Watcher(object):
    running = True
    refresh_delay_secs = 1

    # Constructor
    def __init__(self, watch_file, call_func_on_change=None, *args, **kwargs):
        self._cached_stamp = 0
        self.filename = watch_file
        self.call_func_on_change = call_func_on_change
        self.args = args
        self.kwargs = kwargs

    # Look for changes
    def look(self):
        stamp = os.stat(self.filename).st_mtime
        if stamp != self._cached_stamp:
            self._cached_stamp = stamp
            # File has changed, so do something...
            print('File changed')
            if self.call_func_on_change is not None:
                self.call_func_on_change(*self.args, **self.kwargs)

    # Keep watching in a loop        
    def watch(self):
        while self.running: 
            try: 
                # Look for changes
                time.sleep(self.refresh_delay_secs) 
                self.look() 
            except KeyboardInterrupt: 
                print('\nDone') 
                break 
            except FileNotFoundError:
                # Action on file not found
                pass
            except: 
                print('Unhandled error: %s' % sys.exc_info()[0])

# Call this function each time a change happens
def custom_action(text):
    print(text)

watch_file = 'my_file.txt'

# watcher = Watcher(watch_file)  # simple
watcher = Watcher(watch_file, custom_action, text='yes, changed')  # also call custom action function
watcher.watch()  # start the watch going

2
Bạn có thể lập watch_file_cached_stampđưa vào danh sách, và lặp lại chúng trong một vòng lặp for. Mặc dù không thực sự mở rộng quy mô cho số lượng lớn tệp
4Oh4

Điều này không kích hoạt hành động mỗi khi nó chạy sao? _cached_stamp được đặt thành 0 và sau đó được so sánh với os.stat (self.filename) .st_mtime. _cached_stamp nên được đặt thành os.stat (self.filename) .st_mtime trong hàm tạo, không?
Seanonymous

1
call_func_on_change()sẽ được kích hoạt trong lần chạy đầu tiên look(), nhưng sau đó _cached_stampđược cập nhật, do đó sẽ không được kích hoạt lại cho đến khi giá trị os.stat(self.filename).st_mtime. _cached_stampthay đổi.
4Oh4

1
Bạn có thể đặt giá trị của _cached_stamphàm tạo nếu bạn không muốn call_func_on_change()được gọi trong lần chạy đầu tiên
4Oh4

Tôi đã sử dụng tập lệnh của bạn để gọi một số chức năng thay đổi tập tin. Hàm của tôi không nhận bất kỳ đối số nào không giống như của bạn. Tôi nghĩ rằng để làm cho nó hoạt động tôi cần phải loại bỏ * args, ** kwargs Có vẻ như vậy (tôi chỉ đặt các dòng có thay đổi): self.call_func_on_change(self) def custom_action(): watcher = Watcher(watch_file, custom_action())Nhưng điều này không hoạt động. Hành động chỉ được gọi trong lần lặp đầu tiên: Tệp đã thay đổi Có, đã thay đổi Tệp đã thay đổi Tệp đã thay đổi Tệp đã bắt đầu hoạt động khi tôi giữ * args và gọi nó: watcher = Watcher(watch_file, custom_action)Tôi đấu tranh để tự hỏi tại sao?
zwornik

7

Kiểm tra câu trả lời của tôi cho một câu hỏi tương tự . Bạn có thể thử vòng lặp tương tự trong Python. Trang này gợi ý:

import time

while 1:
    where = file.tell()
    line = file.readline()
    if not line:
        time.sleep(1)
        file.seek(where)
    else:
        print line, # already has newline

Cũng xem phần đuôi câu hỏi () một tệp bằng Python .


Bạn có thể sys.stdout.write (dòng). Mã của bạn không hoạt động nếu tập tin bị cắt ngắn. Python có tệp hàm dựng sẵn ().
JFS

Tôi đã đăng một phiên bản sửa đổi của mã của bạn. Bạn có thể kết hợp nó trong câu trả lời của bạn nếu nó phù hợp với bạn.
jfs

7

Giải pháp đơn giản nhất đối với tôi là sử dụng công cụ của watchdog watchmedo

Từ https://pypi.python.org/pypi/watchdog Bây giờ tôi có một quy trình tìm kiếm các tệp sql trong một thư mục và thực thi chúng nếu cần thiết.

watchmedo shell-command \
--patterns="*.sql" \
--recursive \
--command='~/Desktop/load_files_into_mysql_database.sh' \
.

6

Chà, vì bạn đang sử dụng Python, bạn có thể chỉ cần mở một tệp và tiếp tục đọc các dòng từ nó.

f = open('file.log')

Nếu dòng đọc không trống , bạn xử lý nó.

line = f.readline()
if line:
    // Do what you want with the line

Bạn có thể thiếu rằng vẫn ổn để tiếp tục gọi readline EOF là ổn. Nó sẽ tiếp tục trả về một chuỗi rỗng trong trường hợp này. Và khi một cái gì đó được thêm vào tệp nhật ký, việc đọc sẽ tiếp tục từ nơi nó dừng lại, khi bạn cần.

Nếu bạn đang tìm kiếm một giải pháp sử dụng các sự kiện hoặc một thư viện cụ thể, vui lòng chỉ định điều này trong câu hỏi của bạn. Nếu không, tôi nghĩ rằng giải pháp này là tốt.


6

Đây là một phiên bản đơn giản của mã Kender dường như thực hiện cùng một thủ thuật và không nhập toàn bộ tệp:

# Check file for new data.

import time

f = open(r'c:\temp\test.txt', 'r')

while True:

    line = f.readline()
    if not line:
        time.sleep(1)
        print 'Nothing New'
    else:
        print 'Call Function: ', line

6

Đây là một sửa đổi khác của tập lệnh của Tim Goldan chạy trên các loại unix và thêm trình theo dõi đơn giản để sửa đổi tệp bằng cách sử dụng một lệnh (tệp => thời gian).

cách sử dụng: anythingName.py path_to_dir_to_watch

#!/usr/bin/env python

import os, sys, time

def files_to_timestamp(path):
    files = [os.path.join(path, f) for f in os.listdir(path)]
    return dict ([(f, os.path.getmtime(f)) for f in files])

if __name__ == "__main__":

    path_to_watch = sys.argv[1]
    print('Watching {}..'.format(path_to_watch))

    before = files_to_timestamp(path_to_watch)

    while 1:
        time.sleep (2)
        after = files_to_timestamp(path_to_watch)

        added = [f for f in after.keys() if not f in before.keys()]
        removed = [f for f in before.keys() if not f in after.keys()]
        modified = []

        for f in before.keys():
            if not f in removed:
                if os.path.getmtime(f) != before.get(f):
                    modified.append(f)

        if added: print('Added: {}'.format(', '.join(added)))
        if removed: print('Removed: {}'.format(', '.join(removed)))
        if modified: print('Modified: {}'.format(', '.join(modified)))

        before = after

Cập nhật để hỗ trợ python3
rencedg

4

Như bạn có thể thấy trong bài viết của Tim Golden , được chỉ ra bởi Horst Gutmann , WIN32 tương đối phức tạp và theo dõi các thư mục, không phải là một tệp duy nhất.

Tôi muốn đề nghị bạn xem xét IronPython , đây là một triển khai .NET python. Với IronPython, bạn có thể sử dụng tất cả các chức năng .NET - bao gồm

System.IO.FileSystemWatcher

Mà xử lý các tập tin duy nhất với một giao diện Sự kiện đơn giản .


@Ciasto vì sau đó bạn phải có sẵn Iron Python chứ không phải là bản cài đặt Python cơ bản.
Jon Lồng

1

Đây là một ví dụ về việc kiểm tra một tập tin để thay đổi. Một cách có thể không phải là cách tốt nhất để làm điều đó, nhưng nó chắc chắn là một cách ngắn.

Công cụ tiện dụng để khởi động lại ứng dụng khi thay đổi đã được thực hiện đối với nguồn. Tôi đã thực hiện điều này khi chơi với pygame để tôi có thể thấy các hiệu ứng diễn ra ngay sau khi lưu tệp.

Khi được sử dụng trong pygame, hãy đảm bảo các nội dung trong vòng lặp 'while' được đặt trong vòng lặp trò chơi của bạn hay còn gọi là cập nhật hoặc bất cứ điều gì. Nếu không, ứng dụng của bạn sẽ bị kẹt trong một vòng lặp vô hạn và bạn sẽ không thấy trò chơi của mình cập nhật.

file_size_stored = os.stat('neuron.py').st_size

  while True:
    try:
      file_size_current = os.stat('neuron.py').st_size
      if file_size_stored != file_size_current:
        restart_program()
    except: 
      pass

Trong trường hợp bạn muốn mã khởi động lại mà tôi tìm thấy trên web. Nó đây rồi (Không liên quan đến câu hỏi, mặc dù nó có thể có ích)

def restart_program(): #restart application
    python = sys.executable
    os.execl(python, python, * sys.argv)

Hãy vui vẻ làm cho các điện tử làm những gì bạn muốn họ làm.


Có vẻ như sử dụng .st_mtimethay vì .st_sizesẽ đáng tin cậy hơn và một cách ngắn gọn không kém để làm điều này, mặc dù OP đã chỉ ra rằng anh ta không muốn làm điều đó thông qua bỏ phiếu.
martineau

1
ACTIONS = {
  1 : "Created",
  2 : "Deleted",
  3 : "Updated",
  4 : "Renamed from something",
  5 : "Renamed to something"
}
FILE_LIST_DIRECTORY = 0x0001

class myThread (threading.Thread):
    def __init__(self, threadID, fileName, directory, origin):
        threading.Thread.__init__(self)
        self.threadID = threadID
        self.fileName = fileName
        self.daemon = True
        self.dir = directory
        self.originalFile = origin
    def run(self):
        startMonitor(self.fileName, self.dir, self.originalFile)

def startMonitor(fileMonitoring,dirPath,originalFile):
    hDir = win32file.CreateFile (
        dirPath,
        FILE_LIST_DIRECTORY,
        win32con.FILE_SHARE_READ | win32con.FILE_SHARE_WRITE,
        None,
        win32con.OPEN_EXISTING,
        win32con.FILE_FLAG_BACKUP_SEMANTICS,
        None
    )
    # Wait for new data and call ProcessNewData for each new chunk that's
    # written
    while 1:
        # Wait for a change to occur
        results = win32file.ReadDirectoryChangesW (
            hDir,
            1024,
            False,
            win32con.FILE_NOTIFY_CHANGE_LAST_WRITE,
            None,
            None
        )
        # For each change, check to see if it's updating the file we're
        # interested in
        for action, file_M in results:
            full_filename = os.path.join (dirPath, file_M)
            #print file, ACTIONS.get (action, "Unknown")
            if len(full_filename) == len(fileMonitoring) and action == 3:
                #copy to main file
                ...

1

Đây là một ví dụ hướng đến việc xem các tệp đầu vào ghi không quá một dòng mỗi giây nhưng thường ít hơn rất nhiều. Mục tiêu là nối thêm dòng cuối cùng (ghi gần đây nhất) vào tệp đầu ra được chỉ định. Tôi đã sao chép điều này từ một trong các dự án của tôi và chỉ xóa tất cả các dòng không liên quan. Bạn sẽ phải điền hoặc thay đổi các biểu tượng còn thiếu.

from PyQt5.QtCore import QFileSystemWatcher, QSettings, QThread
from ui_main_window import Ui_MainWindow   # Qt Creator gen'd 

class MainWindow(QMainWindow, Ui_MainWindow):
    def __init__(self, parent=None):
        QMainWindow.__init__(self, parent)
        Ui_MainWindow.__init__(self)
        self._fileWatcher = QFileSystemWatcher()
        self._fileWatcher.fileChanged.connect(self.fileChanged)

    def fileChanged(self, filepath):
        QThread.msleep(300)    # Reqd on some machines, give chance for write to complete
        # ^^ About to test this, may need more sophisticated solution
        with open(filepath) as file:
            lastLine = list(file)[-1]
        destPath = self._filemap[filepath]['dest file']
        with open(destPath, 'a') as out_file:               # a= append
            out_file.writelines([lastLine])

Tất nhiên, lớp QMainWindow bao gồm không bắt buộc, nghĩa là. bạn có thể sử dụng QFileSystemWatcher một mình.


0

Bạn cũng có thể sử dụng một thư viện đơn giản gọi là repyt , đây là một ví dụ:

repyt ./app.py

0

Có vẻ như không ai đã đăng fswatch . Nó là một trình theo dõi hệ thống tập tin đa nền tảng. Chỉ cần cài đặt nó, chạy nó và làm theo lời nhắc.

Tôi đã sử dụng nó với các chương trình python và golang và nó chỉ hoạt động.


0

giải pháp @ 4Oh4 có liên quan thay đổi suôn sẻ cho danh sách các tệp cần xem;

import os
import sys
import time

class Watcher(object):
    running = True
    refresh_delay_secs = 1

    # Constructor
    def __init__(self, watch_files, call_func_on_change=None, *args, **kwargs):
        self._cached_stamp = 0
        self._cached_stamp_files = {}
        self.filenames = watch_files
        self.call_func_on_change = call_func_on_change
        self.args = args
        self.kwargs = kwargs

    # Look for changes
    def look(self):
        for file in self.filenames:
            stamp = os.stat(file).st_mtime
            if not file in self._cached_stamp_files:
                self._cached_stamp_files[file] = 0
            if stamp != self._cached_stamp_files[file]:
                self._cached_stamp_files[file] = stamp
                # File has changed, so do something...
                file_to_read = open(file, 'r')
                value = file_to_read.read()
                print("value from file", value)
                file_to_read.seek(0)
                if self.call_func_on_change is not None:
                    self.call_func_on_change(*self.args, **self.kwargs)

    # Keep watching in a loop
    def watch(self):
        while self.running:
            try:
                # Look for changes
                time.sleep(self.refresh_delay_secs)
                self.look()
            except KeyboardInterrupt:
                print('\nDone')
                break
            except FileNotFoundError:
                # Action on file not found
                pass
            except Exception as e:
                print(e)
                print('Unhandled error: %s' % sys.exc_info()[0])

# Call this function each time a change happens
def custom_action(text):
    print(text)
    # pass

watch_files = ['/Users/mexekanez/my_file.txt', '/Users/mexekanez/my_file1.txt']

# watcher = Watcher(watch_file)  # simple



if __name__ == "__main__":
    watcher = Watcher(watch_files, custom_action, text='yes, changed')  # also call custom action function
    watcher.watch()  # start the watch going


-2

Tôi không biết bất kỳ chức năng cụ thể của Windows. Bạn có thể thử lấy băm MD5 của tệp mỗi giây / phút / giờ (tùy thuộc vào tốc độ bạn cần) và so sánh với băm cuối cùng. Khi nó khác bạn biết rằng tập tin đã được thay đổi và bạn đọc những dòng mới nhất.


-6

Tôi sẽ thử một cái gì đó như thế này.

    try:
            f = open(filePath)
    except IOError:
            print "No such file: %s" % filePath
            raw_input("Press Enter to close window")
    try:
            lines = f.readlines()
            while True:
                    line = f.readline()
                    try:
                            if not line:
                                    time.sleep(1)
                            else:
                                    functionThatAnalisesTheLine(line)
                    except Exception, e:
                            # handle the exception somehow (for example, log the trace) and raise the same exception again
                            raw_input("Press Enter to close window")
                            raise e
    finally:
            f.close()

Vòng lặp kiểm tra nếu có một dòng mới kể từ lần đọc tệp cuối cùng - nếu có, nó đã được đọc và chuyển đến functionThatAnalisesTheLinehàm. Nếu không, script sẽ đợi 1 giây và thử lại quy trình.


4
-1: Mở tệp và đọc các dòng không phải là ý tưởng hay khi các tệp có thể lớn 100 MB. Bạn sẽ phải chạy nó cho từng tệp, điều này sẽ rất tệ khi bạn muốn xem 1000 tập tin.
Jon Lồng

1
Có thật không? Mở tập tin để thay đổi?
Farsheed
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.