ฉันจะดูไฟล์สำหรับการเปลี่ยนแปลงได้อย่างไร


323

ฉันมีไฟล์บันทึกที่เขียนโดยกระบวนการอื่นซึ่งฉันต้องการดูการเปลี่ยนแปลง ทุกครั้งที่มีการเปลี่ยนแปลงฉันต้องการอ่านข้อมูลใหม่เพื่อทำการประมวลผล

วิธีที่ดีที่สุดในการทำเช่นนี้คืออะไร? ฉันหวังว่าจะมีตะขอบางอย่างจากห้องสมุด PyWin32 ฉันพบwin32file.FindNextChangeNotificationฟังก์ชัน แต่ไม่รู้ว่าจะขอให้ดูไฟล์เฉพาะได้อย่างไร

หากใครทำอะไรแบบนี้ฉันจะขอบคุณจริง ๆ ที่ได้ยินว่า ...

[แก้ไข]ฉันควรจะบอกว่าฉันเป็นคนที่ไม่ต้องการการสำรวจ

[แก้ไข]คำสาป! ดูเหมือนว่าสิ่งนี้จะไม่ทำงานกับไดรฟ์เครือข่ายที่แมป ฉันคาดเดาว่า windows จะไม่ 'ได้ยิน' การอัปเดตใด ๆ กับไฟล์ในแบบเดียวกับบนดิสก์ในเครื่อง


1
บน Linux สามารถใช้straceการตรวจสอบการwriteโทรได้
test30

คำตอบของ @ simaoใช้ python-watchdog Python-Watchdog มีเอกสารที่ยอดเยี่ยม -> นี่คือลิงค์ไปยังเอกสาร ["QuickStart"] ซึ่งให้ตัวอย่างรหัสขั้นต่ำที่คอยดูไดเรกทอรีการทำงานปัจจุบัน
Trevor Boyd Smith

คำตอบ:


79

คุณได้ดูเอกสารที่มีอยู่ในhttp://timgolden.me.uk/python/win32_how_do_i/watch_directory_for_changes.html แล้วหรือยัง หากคุณต้องการให้ทำงานภายใต้ Windows เท่านั้นตัวอย่างที่ 2 น่าจะเป็นสิ่งที่คุณต้องการอย่างแน่นอน (หากคุณแลกเปลี่ยนพา ธ ของไดเรกทอรีด้วยไฟล์ที่คุณต้องการดู)

มิเช่นนั้นการสำรวจอาจเป็นตัวเลือกที่ไม่ขึ้นกับแพลตฟอร์มเท่านั้น

หมายเหตุ:ฉันไม่ได้ลองวิธีแก้ไขปัญหาใด ๆ เหล่านี้


5
คำตอบนี้เฉพาะ Windows แต่ปรากฏว่ามีการแก้ไขปัญหาข้ามแพลตฟอร์มสำหรับปัญหานี้แล้วเช่นกัน
Anderson Green

มีเกณฑ์มาตรฐานหรือไม่ถ้ากระบวนการนี้ช้าลงจึงนำไปใช้ในภาษาท้องถิ่นเช่น c ++?
user1767754

เป็นการดีกว่าที่จะแทรกเนื้อหาที่เกี่ยวข้องจากแหล่งที่อ้างถึงเนื่องจากอาจล้าสมัย
Trilarion

2
(1. ) ในตอนท้ายของคำตอบนี้เป็นข้อจำกัดความรับผิดชอบที่แข็งแกร่ง ... "ฉันไม่ได้ลองวิธีแก้ปัญหาเหล่านี้" (2. ) คำตอบนี้มากหรือน้อย"ลิงก์เท่านั้น" คำตอบ (3. ) คำตอบที่กล่าวถึง "การสำรวจความคิดเห็น" แต่ไม่ได้ให้เพิ่มสิ่งใดที่เป็นประโยชน์หลังจากนั้น ... ซึ่งคำตอบ @ Deestanให้ข้อมูลที่ดีเกี่ยวกับการลงคะแนน
Trevor Boyd Smith

283

คุณลองใช้Watchdogหรือไม่

Python API library และ shell Utilities เพื่อตรวจสอบเหตุการณ์ของระบบไฟล์

การตรวจสอบไดเรกทอรีทำได้ง่ายด้วย

  • API ข้ามแพลตฟอร์ม
  • เครื่องมือเชลล์เพื่อเรียกใช้คำสั่งเพื่อตอบสนองต่อการเปลี่ยนแปลงของไดเรกทอรี

เริ่มต้นอย่างรวดเร็วด้วยตัวอย่างง่ายๆในQuickstart ...


56
ติดตั้งด้วยeasy_installหรือไม่ ตรวจสอบ ใบอนุญาตฟรีหรือไม่ ตรวจสอบ แก้ปัญหาบนแพลตฟอร์มใหญ่หรือไม่? ตรวจสอบ ฉันรับรองคำตอบนี้ หมายเหตุเท่านั้น: ตัวอย่างในหน้าโครงการจะไม่ทำงานนอกกรอบ ใช้หนึ่งใน GitHub ของพวกเขาแทน
Inaimathi

6
เราใช้สุนัขเฝ้าบ้าน เราอาจเปลี่ยนเป็น QFileSystemWatcher เพียงแค่คำเตือนที่ยุติธรรม - สุนัขเฝ้าบ้านนั้นดี แต่ยังห่างไกลจากความสมบูรณ์แบบในทุกแพลตฟอร์ม (ในเวลานี้) แต่ละระบบปฏิบัติการมีนิสัยแปลก ๆ ดังนั้นถ้าคุณไม่ทุ่มเทเพื่อทำให้มันสมบูรณ์แบบคุณจะดึงผมออกมา หากคุณเพียงแค่ต้องการดูไฟล์ 10 ไฟล์ฉันจะทำแบบสำรวจ การแคชดิสก์ของระบบปฏิบัติการนั้นมีความเป็นผู้ใหญ่มาก ส่วนใหญ่ใช้สำหรับดูโครงสร้างโฟลเดอร์ขนาดใหญ่ IMHO
SilentSteel

3
คนหนึ่งที่ฉันจับต้องด้วย watchdog คือมันมีการอ้างอิงหลายอย่าง แน่นอนน้อยกว่า PyQt แต่ไม่ได้ผลและให้ความรู้สึกเหมือนวิธีปฏิบัติที่น้อยที่สุดและดีที่สุดวิธีการแก้ปัญหาที่ไม่ได้งานและไม่เหมาะสม
AndreasT

1
@denfromufa ถูกต้องที่นี่ใช่ไหม Watchdog ล็อคไฟล์จริงๆหรือไม่ดังนั้นจึงไม่สามารถแก้ไขพร้อมกันเพื่อเฝ้าดูเฝ้าดูได้หรือไม่ ฉันแทบจะไม่เชื่อว่ามันจะไร้ประโยชน์อย่างสมบูรณ์
Michel Müller

1
@ MichelMüllerฉันเพิ่งตรวจสอบตัวอย่างนี้ (ดูลิงค์ด้านล่าง) และใช้งานได้! ไม่แน่ใจว่ามีอะไรผิดปกติมาก่อน แต่คำตอบนี้ไม่มีตัวอย่างใด ๆ stackoverflow.com/a/18599427/2230844
denfromufa

92

ถ้าการสำรวจดีพอสำหรับคุณฉันแค่เฝ้าดูว่าสถิติการ "แก้ไขเวลา" ของไฟล์เปลี่ยนไปหรือไม่ หากต้องการอ่าน:

os.stat(filename).st_mtime

(โปรดทราบว่าโซลูชันการเปลี่ยนแปลงเนทิฟ Windows ไม่สามารถใช้งานได้ในทุกสถานการณ์เช่นบนไดรฟ์เครือข่าย)

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
คุณจะทำสิ่งนี้ในช่วงเวลาหนึ่งได้อย่างไร?
dopatraman

1
@dopatraman นี่คือวิธีที่คุณสามารถทำได้ในช่วงเวลา `นำเข้า sys เวลานำเข้าผับ = Monkey () ในขณะที่ True: ลอง: time.sleep (1) pub.watch () ยกเว้น KeyboardInterrupt: พิมพ์ ('\ nDone') ยกเว้นยกเว้น : print (ข้อผิดพลาด f'Unhandled: {sys.exc_info () [0]} ') `
Vlad Bezden

สุดยอดวิธีง่ายๆ! if self._cached_stamp is not Noneฉันจะเพิ่มการตรวจสอบเพื่อให้ได้จากการรายงานไฟล์ที่มีการเปลี่ยนแปลงในการทำงานครั้งแรก:
Noumenon

50

หากคุณต้องการโซลูชั่นที่หลากหลายแล้วตรวจสอบQFileSystemWatcher นี่คือตัวอย่างรหัส (ไม่ผ่านการฆ่าเชื้อ):

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
ฉันคิดว่านี่อาจเป็นคำตอบที่ดีที่สุดของพวงเนื่องจากพวกเขา a) พึ่งพาวัตถุ FileSystemwatcher ของ Win32 และไม่สามารถรังเพลิงหรือ b) สำรวจความคิดเห็นสำหรับไฟล์ (ซึ่งไม่ดีต่อประสิทธิภาพและจะไม่ขยาย) มันเป็นเรื่องที่น่าเสียดาย Python ไม่มีสิ่งอำนวยความสะดวกนี้ในตัวเนื่องจาก PyQt เป็นระบบที่ต้องพึ่งพาอย่างมากหากทุกสิ่งที่คุณใช้คือคลาส QFileSystemWatcher
CadentOrange

4
ฉันชอบวิธีนี้ ฉันต้องการชี้ให้เห็นว่าคุณจะต้องมีอินสแตนซ์ QApplication เพื่อให้ทำงานได้ฉันเพิ่ม "app = QtGui.QApplication (sys.argv)" ภายใต้การนำเข้าแล้ว "app.exec_ ()" หลังจากการเชื่อมต่อสัญญาณ
spencewah

เพียงแค่ทดสอบสิ่งนี้บนกล่อง Linux ฉันเห็นว่ามีการเรียกใช้เมธอด directory_changed แต่ไม่ใช่ file_changed
Ken Kinder


ทำไมไม่ใช้PySideสำหรับสิ่งนั้นแทนPyQtการใช้เพียงเล็กน้อย
Ciasto piekarz

29

มันไม่ควรทำงานบน windows (อาจมี cygwin?) แต่สำหรับผู้ใช้ยูนิกซ์คุณควรใช้การเรียกระบบ "fcntl" นี่คือตัวอย่างใน Python ส่วนใหญ่เป็นรหัสเดียวกันถ้าคุณต้องการเขียนใน C (ชื่อฟังก์ชั่นเดียวกัน)

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
ใช้งานได้อย่างมีเสน่ห์ด้วยเคอร์เนล 2.6.31 ในระบบไฟล์ ext4 (บน Ubuntu 10.04) แต่สำหรับไดเรกทอรีเท่านั้น - มันเพิ่ม IOError "ไม่ใช่ไดเรกทอรี" ถ้าฉันใช้กับไฟล์
David Underhill

1
ที่ดี! เหมือนกันสำหรับฉันทำงานกับไดเรกทอรีเท่านั้นและดูไฟล์ในไดเรกทอรีนี้ แต่มันจะไม่ทำงานสำหรับไฟล์ที่ถูกแก้ไขในไดเรกทอรีย่อยดังนั้นดูเหมือนว่าคุณจะต้องเดินผ่านไดเรกทอรีย่อยและดูพวกเขาทั้งหมด (หรือมีวิธีที่ดีกว่าในการทำเช่นนี้?)
lfagundes

20

ตรวจสอบpyinotify

inotify แทนที่ dnotify (จากคำตอบก่อนหน้า) ใน linux ที่ใหม่กว่าและอนุญาตให้ระดับไฟล์มากกว่าการตรวจสอบระดับไดเรกทอรี


5
เพื่อไม่ให้ตัวสั่นสะเทือนกับคำตอบนี้ แต่หลังจากอ่านบทความนี้ฉันจะบอกว่ามันอาจจะไม่เป็นทางออกที่น่าสนใจอย่างที่คิด serpentine.com/blog/2008/01/04/why-you-should-not-use-pyinotify
NuclearPeon

1
pyinotify มีข้อเสียมากมายเริ่มจากฐานรหัสที่ไม่ไพเราะมากถึงการใช้หน่วยความจำ ดีกว่าที่จะมองหาตัวเลือกอื่น ๆ ..
Tyto

13

หลังจากการแฮ็คสคริปต์ของ Tim Golden เล็กน้อยฉันมีสิ่งต่อไปนี้ซึ่งทำงานได้ค่อนข้างดี:

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 )

มันอาจจะทำอย่างไรกับการตรวจสอบข้อผิดพลาดในการโหลดมากขึ้น แต่สำหรับการดูไฟล์บันทึกและทำการประมวลผลบางอย่างก่อนที่จะแยกมันออกไปที่หน้าจอ

ขอบคุณทุกคนสำหรับข้อมูลของคุณ - สิ่งดีๆ!


10

สำหรับการดูไฟล์เดียวที่มีการสำรวจและการอ้างอิงน้อยที่สุดนี่เป็นตัวอย่างที่สมบูรณ์แบบโดยอิงจากคำตอบจากDeestan (ด้านบน):

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
คุณสามารถสร้างwatch_fileและ_cached_stampเป็นรายการและวนซ้ำในลูป for ไม่ได้ขยายขนาดได้ดีถึงไฟล์จำนวนมาก
4Oh4

สิ่งนี้ไม่ก่อให้เกิดการกระทำทุกครั้งที่มันทำงานอยู่หรือ _cached_stamp ถูกตั้งค่าเป็น 0 แล้วเปรียบเทียบกับ os.stat (self.filename) .st_mtime _cached_stamp ควรตั้งค่าเป็น os.stat (self.filename) .st_mtime ใน Constructor ใช่ไหม
Seanonymous

1
call_func_on_change()จะถูกเรียกใช้ในการเรียกใช้ครั้งแรกlook()แต่_cached_stampจะได้รับการอัปเดตดังนั้นจะไม่ถูกเรียกอีกครั้งจนกว่าจะมีos.stat(self.filename).st_mtime. _cached_stampการเปลี่ยนแปลงมูลค่า
4Oh4

1
คุณสามารถกำหนดค่าของ_cached_stampตัวสร้างได้หากคุณไม่ต้องการcall_func_on_change()ถูกเรียกใช้ในการเรียกใช้ครั้งแรก
4Oh4

ฉันใช้สคริปต์ของคุณเพื่อเรียกฟังก์ชั่นบางอย่างเกี่ยวกับการเปลี่ยนแปลงไฟล์ ฟังก์ชั่นของฉันไม่ได้ขัดแย้งอะไรกับคุณเลย ฉันคิดว่าเพื่อให้มันทำงานฉันต้องลบ * args, ** kwargs ดูเหมือนว่า (ฉันใส่เฉพาะบรรทัดที่มีการเปลี่ยนแปลง): self.call_func_on_change(self) def custom_action(): watcher = Watcher(watch_file, custom_action())แต่นี่ไม่ได้ผล การดำเนินการถูกเรียกในระหว่างการทำซ้ำครั้งแรกเท่านั้น: การเปลี่ยนแปลงไฟล์ใช่, การเปลี่ยนแปลงไฟล์การเปลี่ยนแปลงไฟล์การเปลี่ยนแปลงไฟล์การเปลี่ยนแปลงมันเริ่มทำงานเมื่อฉันเก็บ * args และเรียกมันว่า: watcher = Watcher(watch_file, custom_action)ฉันพยายามที่จะสงสัยว่าทำไม?
zwornik

7

ตรวจสอบคำตอบของฉันกับคำถามที่คล้ายกัน คุณสามารถลองวนซ้ำเดียวกันใน Python หน้านี้แนะนำ:

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

ยังเห็นคำถามที่หาง () ไฟล์ที่มีงูหลาม


คุณสามารถ sys.stdout.write (บรรทัด) รหัสของคุณไม่ทำงานหากไฟล์ถูกตัดทอน Python มีไฟล์ฟังก์ชัน builtin ()
jfs

ฉันโพสต์รหัสของคุณในเวอร์ชันที่แก้ไขแล้ว คุณอาจรวมไว้ในคำตอบของคุณถ้ามันเหมาะกับคุณ
jfs

7

ทางออกที่ง่ายที่สุดสำหรับฉันคือการใช้เครื่องมือเฝ้าระวังของ watchdog

จากhttps://pypi.python.org/pypi/watchdogตอนนี้ฉันมีกระบวนการที่ค้นหาไฟล์ sql ในไดเรกทอรีและดำเนินการถ้าจำเป็น

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

6

เนื่องจากคุณใช้ Python คุณสามารถเปิดไฟล์และอ่านบรรทัดต่อไปได้

f = open('file.log')

หากการอ่านบรรทัดไม่ว่างคุณจะดำเนินการ

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

คุณอาจจะพลาดที่จะสามารถโทรออกได้ readline EOF ต่อไป มันจะส่งคืนสตริงว่างในกรณีนี้ และเมื่อสิ่งที่ผนวกเข้ากับล็อกไฟล์การอ่านจะดำเนินต่อจากที่หยุดตามที่คุณต้องการ

หากคุณกำลังมองหาโซลูชันที่ใช้งานกิจกรรมหรือห้องสมุดเฉพาะกรุณาระบุในคำถามของคุณ มิฉะนั้นฉันคิดว่าวิธีนี้ใช้ได้ดี


6

นี่เป็นเวอร์ชั่นย่อของรหัส Kender ที่ดูเหมือนจะทำแบบเดียวกันและไม่นำเข้าไฟล์ทั้งหมด:

# 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

นี่คือการปรับเปลี่ยนสคริปต์ของ Tim Goldan ที่ทำงานในประเภท unix และเพิ่มตัวเฝ้าดูอย่างง่ายสำหรับการแก้ไขไฟล์โดยใช้ dict (file => time)

การใช้งาน: 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

อัปเดตเพื่อรองรับ python3
ronedg

4

อย่างที่คุณเห็นในบทความของ Tim Goldenชี้โดยHorst Gutmannว่า WIN32 นั้นค่อนข้างซับซ้อนและเฝ้าดูไดเรกทอรีไม่ใช่ไฟล์เดียว

ฉันอยากจะแนะนำให้คุณดูในIronPythonซึ่งเป็นการนำไปปฏิบัติของ. NET ด้วย IronPython คุณสามารถใช้ฟังก์ชัน. NETทั้งหมดรวมถึง

System.IO.FileSystemWatcher

ซึ่งจัดการไฟล์เดียวด้วยส่วนต่อประสานที่ใช้งานง่าย


@Ciasto เพราะคุณต้องมี Iron Python มากกว่าการติดตั้ง Python พื้นฐาน
Jon Cage

1

นี่เป็นตัวอย่างของการตรวจสอบไฟล์สำหรับการเปลี่ยนแปลง หนึ่งที่อาจไม่ใช่วิธีที่ดีที่สุดในการทำ แต่แน่ใจว่าเป็นวิธีที่สั้น

เครื่องมือที่มีประโยชน์สำหรับการรีสตาร์ทแอปพลิเคชันเมื่อมีการเปลี่ยนแปลงแหล่งที่มา ฉันทำสิ่งนี้เมื่อเล่นกับ pygame ดังนั้นฉันจึงเห็นเอฟเฟกต์เกิดขึ้นทันทีหลังจากบันทึกไฟล์

เมื่อใช้ใน pygame ตรวจสอบให้แน่ใจว่าเนื้อหาใน 'while' loop ถูกวางไว้ในลูปเกมของคุณหรือที่อัปเดต ไม่เช่นนั้นแอปพลิเคชันของคุณจะติดอยู่ในวงวนไม่ จำกัด และคุณจะไม่เห็นการอัปเดตเกมของคุณ

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

ในกรณีที่คุณต้องการรหัสรีสตาร์ทที่ฉันพบบนเว็บ นี่มันคือ (ไม่เกี่ยวข้องกับคำถามแม้ว่าอาจมีประโยชน์)

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

ขอให้สนุกกับการทำให้อิเล็กตรอนทำในสิ่งที่คุณต้องการ


ดูเหมือนว่าการใช้งาน.st_mtimeแทน.st_sizeจะเชื่อถือได้มากกว่าและวิธีการทำเช่นนี้สั้น ๆ อย่างเท่าเทียมกันแม้ว่า OP ได้ระบุว่าเขาไม่ต้องการทำผ่านการสำรวจ
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

นี่คือตัวอย่างที่เน้นไปที่การรับชมไฟล์อินพุตที่เขียนไม่เกินหนึ่งบรรทัดต่อวินาที แต่มักจะน้อยกว่ามาก เป้าหมายคือการต่อท้ายบรรทัดสุดท้าย (การเขียนล่าสุด) กับไฟล์เอาต์พุตที่ระบุ ฉันได้คัดลอกสิ่งนี้จากหนึ่งในโครงการของฉันและเพิ่งลบบรรทัดที่ไม่เกี่ยวข้องทั้งหมด คุณจะต้องกรอกหรือเปลี่ยนสัญลักษณ์ที่หายไป

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])

แน่นอนคลาส QMainWindow ที่ครอบคลุมไม่จำเป็นต้องใช้อย่างเคร่งครัดเช่น คุณสามารถใช้ QFileSystemWatcher เพียงอย่างเดียว



0

ดูเหมือนว่าไม่มีใครโพสต์fswatch fswatchเป็นผู้เฝ้าดูระบบไฟล์ข้ามแพลตฟอร์ม เพียงติดตั้งรันและปฏิบัติตามคำแนะนำ

ฉันใช้มันกับโปรแกรมหลามและ golang และมันใช้งานได้


0

โซลูชั่น @ 4Oh4 ที่เกี่ยวข้องเปลี่ยนแปลงได้อย่างราบรื่นสำหรับรายการไฟล์ที่ต้องดู

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

ฉันไม่รู้ฟังก์ชันเฉพาะของ Windows คุณสามารถลองรับ MD5 hash ของไฟล์ทุกวินาที / นาที / ชั่วโมง (ขึ้นอยู่กับความเร็วที่คุณต้องการ) และเปรียบเทียบกับแฮชสุดท้าย เมื่อมันแตกต่างคุณรู้ว่าไฟล์มีการเปลี่ยนแปลงและคุณอ่านบรรทัดใหม่ล่าสุด


-6

ฉันจะลองแบบนี้

    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()

การวนซ้ำจะตรวจสอบว่ามีบรรทัดใหม่หรือไม่ตั้งแต่มีการอ่านไฟล์ครั้งล่าสุดถ้ามีจะเป็นการอ่านและส่งผ่านไปยังfunctionThatAnalisesTheLineฟังก์ชัน ถ้าไม่ใช่สคริปต์จะรอ 1 วินาทีและลองใหม่อีกครั้ง


4
-1: การเปิดไฟล์และอ่านบรรทัดไม่ใช่ความคิดที่ดีเมื่อไฟล์อาจมีขนาด 100 MB คุณจะต้องเรียกใช้มันสำหรับไฟล์ทุกไฟล์เช่นกันซึ่งจะไม่ดีเมื่อคุณต้องการดูไฟล์จำนวน 1,000 ไฟล์
Jon Cage

1
จริงๆ? กำลังเปิดไฟล์สำหรับการเปลี่ยนแปลงหรือไม่
Farsheed
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.