मैं परिवर्तनों के लिए फ़ाइल कैसे देखूं?


323

मेरे पास एक अन्य प्रक्रिया द्वारा लिखी जा रही एक लॉग फ़ाइल है जिसे मैं परिवर्तनों के लिए देखना चाहता हूं। हर बार जब कोई बदलाव होता है तो मैं उस पर कुछ प्रोसेसिंग करने के लिए नया डेटा पढ़ना चाहूंगा।

ऐसा करने का सबसे अच्छा तरीका क्या है? मैं उम्मीद कर रहा था कि PyWin32 लाइब्रेरी से किसी प्रकार का हुक होगा। मुझे win32file.FindNextChangeNotificationफ़ंक्शन मिल गया है, लेकिन यह पता नहीं है कि इसे किसी विशिष्ट फ़ाइल को देखने के लिए कैसे पूछना है।

अगर किसी ने ऐसा कुछ किया है तो मैं वास्तव में आभारी हूँ कि कैसे ...

[संपादित करें] मुझे उल्लेख करना चाहिए था कि मैं एक समाधान के बाद था जिसे मतदान की आवश्यकता नहीं है।

[संपादित करें] शाप! ऐसा लगता है कि यह मैप्ड नेटवर्क ड्राइव पर काम नहीं करता है। मैं अनुमान लगा रहा हूं कि जिस तरह से यह एक स्थानीय डिस्क पर होता है, फाइल को कोई अपडेट नहीं करता है।


1
लिनक्स पर कोई भी इसके लिए straceनिगरानी writeकॉल का उपयोग कर सकता है
टेस्ट

@ सिमाओ का जवाब अजगर-प्रहरी का उपयोग करता है। पायथन-वॉचडॉग के पास महान दस्तावेज हैं -> यहां ["क्विकस्टार्ट"] प्रलेखन की एक कड़ी है जो एक न्यूनतम कोड उदाहरण प्रदान करता है जो वर्तमान कार्यशील निर्देशिका को देखता है।
ट्रेवर बॉयड स्मिथ

जवाबों:


79

क्या आपने http://timgolden.me.uk/python/win32_how_do_i/watch_directory_for_changes.html पर उपलब्ध दस्तावेज को पहले ही देख लिया है ? यदि आपको केवल विंडोज के तहत काम करने के लिए इसकी आवश्यकता है तो दूसरा उदाहरण वास्तव में वही है जो आप चाहते हैं (यदि आप उस निर्देशिका के पथ का आदान-प्रदान करते हैं जिसे आप देखना चाहते हैं।

अन्यथा, मतदान शायद केवल वास्तव में प्लेटफ़ॉर्म-स्वतंत्र विकल्प होगा।

ध्यान दें: मैंने इनमें से किसी भी समाधान की कोशिश नहीं की है।


5
यह उत्तर विंडोज-विशिष्ट है, लेकिन ऐसा प्रतीत होता है कि इस समस्या के कुछ क्रॉस-प्लेटफ़ॉर्म समाधान यहां भी पोस्ट किए गए हैं।
एंडरसन ग्रीन

क्या कोई बेंचमार्क है, यदि यह प्रक्रिया धीमी है तो इसे c ++ जैसी मूल भाषा में लागू किया जा सकता है?
14:17 बजे user1767754

उद्धृत स्रोतों से प्रासंगिक सामग्री सम्मिलित करना बेहतर है क्योंकि वे पुराने हो सकते हैं।
त्रिशूल

2
(1.) इस उत्तर के अंत में एक मजबूत अस्वीकरण है ... "मैंने इनमें से किसी भी समाधान की कोशिश नहीं की है"। (२.) यह उत्तर कमोबेश एक "लिंक ओनली" उत्तर है (३.) उत्तर "पोलिंग" का उल्लेख करता है, लेकिन उसके बाद कुछ भी मददगार नहीं देता है ... जहाँ @ देस्तान का जवाब मतदान पर कुछ अच्छी जानकारी प्रदान करता है।
ट्रेवर बॉयड स्मिथ

283

क्या आपने वॉचडॉग का उपयोग करने की कोशिश की ?

पायथन एपीआई पुस्तकालय और फ़ाइल सिस्टम घटनाओं की निगरानी के लिए शेल उपयोगिताओं।

निर्देशिका की निगरानी के साथ आसान बना दिया

  • एक क्रॉस-प्लेटफॉर्म एपीआई।
  • निर्देशिका परिवर्तन के जवाब में कमांड चलाने के लिए एक शेल टूल।

क्विकस्टार्ट में एक सरल उदाहरण के साथ जल्दी शुरू करें ...


56
के साथ स्थापित करने योग्य है easy_install? चेक। निःशुल्क अनुज्ञापत्र? जाँच करें । बड़े प्लेटफार्मों पर समस्या हल करता है? जाँच करें । मैं इस जवाब का समर्थन करता हूं। केवल ध्यान दें: उनके परियोजना पृष्ठ पर उदाहरण बॉक्स से बाहर काम नहीं करता है। इसके बजाय उनके गिथब पर एक का उपयोग करें ।
इनिमाथी

6
हम प्रहरी का उपयोग करते हैं। हम QFileSystemWatcher पर जा सकते हैं। बस एक निष्पक्ष चेतावनी- वॉचडॉग अच्छा है लेकिन सभी प्लेटफार्मों पर (इस समय) से बिल्कुल सही है। प्रत्येक OS में यह आइडियलसंकल्प है। इसलिए, जब तक आप इसे परफेक्ट बनाने के लिए समर्पित नहीं होंगे, तब तक आप अपने बालों को बाहर निकालेंगे। अगर आप 10 फाइलें देखना चाहते हैं, तो मैं मतदान करूंगा। ओएस डिस्क कैशिंग बहुत परिपक्व है और वॉचडॉग में किसी भी तरह से मतदान एपीआई शामिल हैं। यह मुख्य रूप से विशाल फ़ोल्डर संरचनाओं IMHO देखने के लिए है।
साइलेंटसेटल

3
प्रहरी के साथ मेरी एक पकड़ है, कि इसकी कई निर्भरताएँ हैं। निश्चित रूप से, PyQt की तुलना में कम है, लेकिन यह काम नहीं करता है और न्यूनतम, सर्वोत्तम अभ्यास, एक-नौकरी-और-यह-यह-सही समाधान की तरह महसूस करता है।
एंड्रियास

1
क्या @denfromufa यहाँ सही है? क्या वॉचडॉग वास्तव में फाइलों को लॉक करता है, इसलिए उन्हें देखने के लिए समवर्ती रूप से संपादित नहीं किया जा सकता है? मैं शायद ही विश्वास कर पाऊं, यह पूरी तरह से बेकार होगा।
मिशेल मुलर

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 आयात समय पब = बंदर () जबकि सही: try: time.sleep (1) pub.watch () कीबोर्ड के अलावा: प्रिंट ('nDone') ब्रेक को छोड़कर : प्रिंट (f'Unhandled त्रुटि: {sys.exc_info () [0]} ') `
व्लाद बेज्डन

महान सरल समाधान! मैंने इसे पहले रन में परिवर्तित की गई फ़ाइल की रिपोर्टिंग से रखने के लिए एक चेक जोड़ा if self._cached_stamp is not None:।
नौमेनन

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
मुझे लगता है कि यह संभवतः दिए गए गुच्छा का सबसे अच्छा जवाब है कि वे या तो एक) Win32 के फाइलसिस्टम वॉचर ऑब्जेक्ट पर भरोसा करते हैं और फाइल के लिए पोल (पोर्ट नहीं किया जा सकता है या नहीं किया जा सकता है) (जो प्रदर्शन के लिए खराब है और स्केल नहीं करेगा)। यह अफ़सोस की बात है कि पायथन में यह सुविधा नहीं है क्योंकि यदि आप सभी का उपयोग कर रहे हैं तो यह एक बहुत बड़ी निर्भरता है क्यूईइल सिस्टम सिस्टमचैकर वर्ग।
CadentOrange

4
मुझे यह समाधान पसंद है। मैं इंगित करना चाहता था कि आपको काम करने के लिए एक QApplication उदाहरण की आवश्यकता होगी, मैंने आयात के तहत "app = QtGui.QApplication (sys.argv)" सही जोड़ा और फिर सिग्नल कनेक्शन के बाद "app.exec_ (")।
12

बस एक लिनक्स बॉक्स पर यह परीक्षण, मैं देख रहा हूँ कि directory_changed विधि कहा जा रहा है, लेकिन file_changed नहीं।
केन किंडर

@CadentOrange, अगर आपको pyQt निर्भरता पसंद नहीं है, तो watchdogपैकेज सही उत्तर है
माइक पेनिंगटन

इतने छोटे उपयोग के PySideबदले उसके लिए उपयोग क्यों न PyQtकरें।
Ciasto piekarz

29

यह विंडोज़ पर काम नहीं करना चाहिए (शायद साइबरविन के साथ?), लेकिन यूनिक्स उपयोगकर्ता के लिए, आपको "fcntl" सिस्टम कॉल का उपयोग करना चाहिए। यहाँ पायथन में एक उदाहरण है। यदि आप इसे 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 "निर्देशिका नहीं" उठाता है अगर मैं इसे एक फ़ाइल के साथ उपयोग करता हूं।
डेविड अंडरहिल

1
महान! मेरे लिए भी, केवल निर्देशिका के लिए काम करता है और इस निर्देशिका में फ़ाइलें देखता है। लेकिन यह उपनिर्देशिकाओं में संशोधित फ़ाइलों के लिए काम नहीं करेगा, इसलिए ऐसा लगता है कि आपको उपनिर्देशिकाएं चलने और उन सभी को देखने की आवश्यकता है। (या ऐसा करने का एक बेहतर तरीका है?)
lfagundes

20

Pyinotify की जाँच करें

inotify की जगह नए linuxes में dnotify (पहले के उत्तर से) को हटा दें और डायरेक्टरी-लेवल मॉनिटरिंग के बजाय फाइल-लेवल की अनुमति देता है।


5
इस उत्तर पर कोई टालमटोल नहीं करना चाहिए, लेकिन इस लेख को पढ़ने के बाद, मैं कहूंगा कि यह विचार के रूप में एक समाधान के रूप में नहीं हो सकता है। serpentine.com/blog/2008/01/04/why-you-should-not-use-pyinotify
NuclearPeon

1
pyinotify में बहुत सारे नुकसान हैं जो बहुत ही अनहेल्दी कोड बेस से मेमोरी खपत तक शुरू होते हैं। अन्य विकल्पों की तलाश के लिए बेहतर है ..
Tyto

13

अच्छी तरह से टिम गोल्डन की स्क्रिप्ट को हैक करने के बाद, मेरे पास निम्नलिखित हैं जो काफी अच्छी तरह से काम करते हैं:

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

मतदान, और न्यूनतम निर्भरता वाली एक भी फ़ाइल देखने के लिए, यहां डेस्टन (ऊपर) के उत्तर के आधार पर एक पूरी तरह से fleshed-out उदाहरण है :

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एक लूप के लिए उन पर पुनरावृति कर सकते हैं। वास्तव में फ़ाइलों की बड़ी संख्या के लिए अच्छी तरह से पैमाने पर नहीं है
4Oh4

क्या यह हर बार चलने पर कार्रवाई को ट्रिगर नहीं करता है? _caked_stamp को os.stat (self.filename) .st_mtime की तुलना में 0 पर सेट किया जाता है। _cached_stamp को os.stat (self.filename) पर सेट किया जाना चाहिए। निर्माणकर्ता में .st_mtime, नहीं?
22

1
call_func_on_change()के पहले रन पर ट्रिगर किया जाएगा look(), लेकिन फिर _cached_stampअद्यतन किया जाता है, इसलिए os.stat(self.filename).st_mtime. _cached_stampपरिवर्तन के मूल्य तक फिर से ट्रिगर नहीं किया जाएगा ।
ओएच 4

1
_cached_stampयदि आप call_func_on_change()पहले रन पर नहीं बुलाया जाना चाहते हैं तो आप कंस्ट्रक्टर का मूल्य निर्धारित कर सकते हैं
4O44

मैंने फ़ाइल परिवर्तन पर कुछ फ़ंक्शन को कॉल करने के लिए आपकी स्क्रिप्ट का उपयोग किया है। मेरा कार्य आपके विपरीत कोई तर्क नहीं लेता है। मैंने सोचा था कि इसे काम करने के लिए मुझे * 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

इसी तरह के प्रश्न के लिए मेरे उत्तर की जाँच करें । आप पायथन में एक ही लूप आज़मा सकते हैं। यह पृष्ठ बताता है:

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 (लाइन) कर सकते हैं। यदि फ़ाइल काट दी जाती है तो आप कोड काम नहीं करते हैं। पायथन में बिल्डिन फ़ंक्शन फ़ाइल () है।
jfs

मैंने आपके कोड का एक संशोधित संस्करण पोस्ट किया है। यदि यह आपके लिए काम करता है तो आप इसे अपने उत्तर में शामिल कर सकते हैं।
jfs

7

मेरे लिए सबसे सरल समाधान वॉचडॉग के टूल वॉचमेडो का उपयोग कर रहा है

Https://pypi.python.org/pypi/watchdog से अब मेरे पास एक ऐसी प्रक्रिया है जो निर्देशिका में sql फ़ाइलों को देखती है और यदि आवश्यक हो तो उन्हें निष्पादित करती है।

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

6

ठीक है, चूंकि आप पायथन का उपयोग कर रहे हैं, तो आप बस एक फ़ाइल खोल सकते हैं और उससे लाइनें पढ़ सकते हैं।

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

यह टिम गोल्डन की स्क्रिप्ट का एक और संशोधन है जो यूनिक्स प्रकारों पर चलता है और एक तानाशाही (फ़ाइल => समय) का उपयोग करके फ़ाइल संशोधन के लिए एक सरल द्रष्टा जोड़ता है।

उपयोग: जो भी हो Name.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

जैसा कि आप टिम गोल्डन के लेख में देख सकते हैं , जो हॉर्स्ट गुटमैन द्वारा इंगित किया गया है , Win32 अपेक्षाकृत जटिल है और एक भी फाइल नहीं, बल्कि डायरेक्टरीज़ देखता है।

मैं आपको सुझाव देना चाहता हूं कि आप IronPython को देखें , जो .NET python कार्यान्वयन है। IronPython के साथ आप सभी .NET कार्यक्षमता का उपयोग कर सकते हैं - सहित

System.IO.FileSystemWatcher

जो एक सिंपल इवेंट इंटरफेस के साथ सिंगल फाइल को हैंडल करता है।


@ Ciasto क्योंकि तब आपके पास एक मूल पायथन इंस्टॉलेशन के बजाय आयरन पायथन उपलब्ध होना चाहिए।
जॉन केज

1

यह परिवर्तनों के लिए फ़ाइल की जाँच करने का एक उदाहरण है। एक जो ऐसा करने का सबसे अच्छा तरीका नहीं हो सकता है, लेकिन यह एक छोटा तरीका है।

जब स्रोत में परिवर्तन किया गया हो तब अनुप्रयोग को पुनः आरंभ करने के लिए आसान उपकरण। मैंने इसे pygame के साथ खेलते समय बनाया था ताकि मैं फाइल सेव के तुरंत बाद प्रभाव देख सकूं।

जब pygame में उपयोग किया जाता है, तो सुनिश्चित करें कि सामान 'जबकि' लूप में आपके गेम लूप उर्फ ​​अपडेट या जो भी हो, में रखा गया है। अन्यथा आपका एप्लिकेशन अनंत लूप में फंस जाएगा और आप अपने गेम को अपडेट नहीं देखेंगे।

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करना अधिक विश्वसनीय और ऐसा करने का एक समान तरीका होगा, हालांकि ओपी ने संकेत दिया है कि वह इसे मतदान के माध्यम से नहीं करना चाहते थे।
मार्टीन्यू

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

आप एक साधारण लाइब्रेरी भी इस्तेमाल कर सकते हैं जिसे रेपिट कहते हैं , यहाँ एक उदाहरण है:

repyt ./app.py

0

लगता है कि कोई भी पोस्ट किया गया है fswatch । यह एक क्रॉस-प्लेटफ़ॉर्म फ़ाइल सिस्टम वॉचर है। बस इसे स्थापित करें, इसे चलाएं और संकेतों का पालन करें।

मैंने इसका उपयोग अजगर और गोलंग कार्यक्रमों के साथ किया है और यह सिर्फ काम करता है।


0

संबंधित @ 4O4 समाधान देखने के लिए फ़ाइलों की एक सूची के लिए एक चिकनी परिवर्तन;

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

मुझे कोई विंडोज विशिष्ट फ़ंक्शन नहीं पता है। आप हर दूसरे / मिनट / घंटे फ़ाइल का MD5 हैश प्राप्त करने की कोशिश कर सकते हैं (यह निर्भर करता है कि आपको कितनी जल्दी चाहिए) और अंतिम हैश से तुलना करें। जब यह अलग हो जाता है तो आप जानते हैं कि फ़ाइल बदल दी गई है और आप सबसे नई लाइनें पढ़ते हैं।


-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 एमबी की हो सकती हैं। आपको इसे प्रत्येक फ़ाइल के लिए भी चलाना होगा जो 1000 की फाइलों को देखने के दौरान खराब होगी।
जॉन केज

1
वास्तव में? परिवर्तनों के लिए फ़ाइल खोलना?
21
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.