Pythonã§ãã¡ã¤ã«ã®å¤æ´ãç£è¦ãã(OSéä¾åã»PyGObject使ç¨)
ã©ã¤ãã©ãªGLibã®ã¡ã¤ã³ã«ã¼ãã«ã¯å®æçã«é¢æ°ãå¼ã³åºãä»çµã¿ãããããPyGTK上のタイマー処理についてãã§æ±ã£ã¦ããããããç¨ãã¦ãã¡ã¤ã«ã®ã¿ã¤ã ã¹ã¿ã³ãã宿çã«åå¾ããååã®çµæã¨æ¯è¼ããããã«ãããã¨ã§ããã¡ã¤ã«ã夿´ãããã®ãç£è¦ããæ´æ°ãããã¨ãã«å¦çãå®è¡ããã¨ãã£ããã¨ãè¡ããããã®æ¹æ³ã¯OSã«ä¾åããªã(GLibã«ä¾åããã®ã¿)ã
ãªããLinuxã«ã¼ãã«ã«ã¯ãã¡ã¤ã«/ãã£ã¬ã¯ããªã®æ§ã
ãªå¤æ´ãç£è¦ããinotifyã¨ããæ©è½ããã*1ããããã¯Linuxåºæã®æ©è½ã§ãä»ã®(åºãæå³ã§ã®)UNIXç³»OSã§ã¯ä½¿ããªãã
(2010/4/12)ãGIOライブラリのファイル変更監視機能を用いるãã§ã¯ãPyGObjectã®GIOã©ã¤ãã©ãªã®è¨èªãã¤ã³ãã£ã³ã°ãç¨ãã¦ããé«åº¦ãªå¤æ´ç£è¦ãè¡ãæ¹æ³ã«ã¤ãã¦ãæ±ã£ã¦ããã
æçµæ´æ°æ¥æã®åå¾ã«é¢ããã¡ã¢
Pythonã§æçµæ´æ°æ¥æãåå¾ããã«ã¯
os.stat([ãã¡ã¤ã«ã®ãã¹]).st_mtime
ã§åãåºãã
(2010/2/27)os.path.getmtime()ã®ã»ããæ¥½ã«åå¾ã§ããã
ä¾
ããã¹ãå
¥åæ¬ã«ãã¡ã¤ã«ã®çµ¶å¯¾ãã¹ãå
¥åãã¦ãWatchããã¿ã³(ãã°ã«ãã¿ã³)ãæ¼ãã¨ç£è¦ãéå§ããã1ç§ã«1å*2æçµæ´æ°æ¥æããã§ãã¯ãããã¡ã¤ã«ã䏿¸ãããããtouchã³ãã³ãã«ããã¿ã¤ã ã¹ã¿ã³ãã夿´ããããããã¨ãã«ããã¹ããã¥ã¼å
ã«éç¥ã¡ãã»ã¼ã¸ã表示ããããWatchããã¿ã³ãããä¸åº¦æ¼ãã¦å
ã«æ»ãã¨ç£è¦ãè§£é¤ããã
ä¸ã®ããã°ã©ã ã¯PyGObjectã®ä»PyGTKãç¨ãã¦ãã(ã©ã¡ããã®ããã±ã¼ã¸ããªããã°ã¤ã³ã¹ãã¼ã«ãã¦ããå¿
è¦ããã)ã
[ä»»æ]ãã¡ã¤ã«å: filewatchtest.py
#! /usr/bin/python # -*- encoding: utf-8 -*- import time import sys import os try: import pygtk pygtk.require('2.0') except: pass try: import gtk except: print >> sys.stderr, 'Error: PyGTK is not installed' sys.exit(1) try: from glib import timeout_add_seconds as glib_timeout_add_seconds from glib import source_remove as glib_source_remove except: try: from gobject import timeout_add_seconds as glib_timeout_add_seconds from gobject import source_remove as glib_source_remove except: print >> sys.stderr, 'Error: cannot import GLib functions' sys.exit(1) class MainWindow(gtk.Window): """ ã¡ã¤ã³ã¦ã£ã³ã㦠""" def __init__(self, *args, **kwargs): gtk.Window.__init__(self, *args, **kwargs) # ã·ã§ã¼ãã«ãããã¼(ã¢ã¯ã»ã©ã¬ã¼ã¿) self.__accelgroup = gtk.AccelGroup() self.add_accel_group(self.__accelgroup) # ã¡ãã¥ã¼é ç® self.__item_quit = gtk.ImageMenuItem(gtk.STOCK_QUIT, self.__accelgroup) self.__menu_file = gtk.Menu() self.__menu_file.add(self.__item_quit) self.__item_file = gtk.MenuItem('_File') self.__item_file.props.submenu = self.__menu_file self.__menubar = gtk.MenuBar() self.__menubar.append(self.__item_file) # ãã¡ã¤ã«åã®ããã¹ãå ¥åæ¬ self.__entry = gtk.Entry() # åç §ãã¿ã³ self.__btn_browse = gtk.Button('...') # ç£è¦éå§/忢ãã¿ã³ self.__btn_watch = gtk.ToggleButton('Watch') self.__btn_watch.props.sensitive = False # ã¡ãã»ã¼ã¸åºåç¨ããã¹ããã¥ã¼ self.__textbuf = gtk.TextBuffer() self.__textview = gtk.TextView(self.__textbuf) self.__textview.props.editable = False self.__sw = gtk.ScrolledWindow() self.__sw.add(self.__textview) self.__sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) # ã¬ã¤ã¢ã¦ãç¨ã³ã³ãã self.__hbox = gtk.HBox() self.__hbox.pack_start(self.__entry) self.__hbox.pack_start(self.__btn_browse, expand=False, fill=False) self.__hbox.pack_start(self.__btn_watch, expand=False, fill=False) self.__vbox = gtk.VBox() self.__vbox.pack_start(self.__menubar, expand=False, fill=False) self.__vbox.pack_start(self.__hbox, expand=False, fill=False) self.__vbox.pack_start(self.__sw) # ã·ã°ãã« self.connect('delete_event', gtk.main_quit) self.__item_quit.connect('activate', gtk.main_quit) self.__entry.connect('changed', self.__on_entry_changed) self.__btn_browse.connect('clicked', self.__on_button_browse_clicked) self.__id_btnsig = self.__btn_watch.connect('toggled', self.__on_button_watch_toggled) # ã¦ã£ã³ã㦠self.add(self.__vbox) self.set_size_request(400, 300) def __on_entry_changed(self, widget): """ ããã¹ãå ¥åæ¬ã®ä¸èº«ã夿´ãããã¨ãã®å¦ç """ self.__btn_watch.props.sensitive = os.access(widget.props.text, os.R_OK) def __on_button_browse_clicked(self, widget): """ ãã¿ã³ãã¯ãªãã¯ãããã¨ãã®å¦ç """ opendlg = gtk.FileChooserDialog(title='Select file', parent=self, buttons=(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_OPEN, gtk.RESPONSE_ACCEPT)) opendlg.set_local_only(True) if opendlg.run() == gtk.RESPONSE_ACCEPT: self.__entry.set_text(opendlg.get_filename()) opendlg.destroy() def __on_button_watch_toggled(self, widget): """ ç£è¦ãã¿ã³ã®ç¶æ ãåãæ¿ããããã¨ãã®å¦ç """ if widget.props.active: # ç£è¦éå§ try: self.__mtime = os.path.getmtime(self.__entry.props.text) except OSError, (errno, msg): self.__append_log_and_scroll('cannot stat "%s"\n errno: %d\n message: %s\n' % (self.__entry.props.text, errno, msg)) # ãã°ã«ãã¿ã³ãå ã«æ»ãããã®éãã³ãã©ã¯å¼ã°ããªãããã«ãã # connect()ã®æ»ãå¤ãhandler_block()/handler_unblock()ã«æå® self.__btn_watch.handler_block(self.__id_btnsig) self.__btn_watch.props.active = False self.__btn_watch.handler_unblock(self.__id_btnsig) return self.__entry.props.sensitive = False self.__btn_browse.props.sensitive = False self.__id_watch = glib_timeout_add_seconds(1, self.__to_watch_file) self.__append_log_and_scroll('start watching "%s" (%s)\n' % (self.__entry.props.text, time.ctime(None))) else: # ç£è¦åæ¢ glib_source_remove(self.__id_watch) self.__append_log_and_scroll('stop watching "%s"\n' % self.__entry.props.text) self.__entry.props.sensitive = True self.__btn_browse.props.sensitive = True def __append_log_and_scroll(self, text): """ ããã¹ããã¥ã¼ã«æååã追å ãã¦æå¾ã«ã¹ã¯ãã¼ã« """ self.__textbuf.place_cursor(self.__textbuf.get_end_iter()) self.__textbuf.insert_at_cursor(text) self.__textview.scroll_to_mark(self.__textbuf.get_insert(), 0) def __to_watch_file(self): """ ãã¡ã¤ã«ã®æçµæ´æ°æ¥æããã§ã㯠""" try: new_mtime = os.path.getmtime(self.__entry.props.text) except OSError, (errno, msg): self.__append_log_and_scroll('cannot stat "%s"\n errno: %d\n message: %s\n' % (self.__entry.props.text, errno, msg)) self.__btn_watch.props.active = False # ããã§source_remove()ãããã®ã§ return False # æ»ãå¤ã¯Falseã§ãªãã¦ãOK # æ°ããåå¾ããã¿ã¤ã ã¹ã¿ã³ãã以åè¨æ¶ãããã®ã¨ç°ãªãã°æ´æ°ããã¦ãã if self.__mtime != new_mtime: self.__mtime = new_mtime # æ°ãããã®ãè¨æ¶ # æ´æ°ãããã¨ãã«è¡ãå¦çãããã«è¨è¿° self.__append_log_and_scroll('file "%s" has been updated (%s)\n' % (self.__entry.props.text, time.ctime(self.__mtime))) # source_remove()ãããã¾ã§ç¡éã«ç¹°ãè¿ã return True; class PyGTKFileWatchTest: """ ãã¡ã¤ã«å¤æ´ç£è¦ã®ãã¹ã """ def main(self): """ ã¢ããªã±ã¼ã·ã§ã³ã®ã¡ã¤ã³å¦ç """ win = MainWindow() win.show_all() gtk.main() if __name__ == '__main__': app = PyGTKFileWatchTest() app.main()
(2010/2/27)PyGObjectã®ããããã£ãç¨ããããã«ä¿®æ£ããä»ãos.path.getmtime()ã®ä½¿ç¨ãªã©ãä¸é¨ã微調æ´(åä½ã¯ä»¥åã¨åä¸)
é¢é£è¨äº:
åèURL:
*1:Pythonããå©ç¨ããã®ã§ããã°pyinotifyã¨ããããã±ã¼ã¸ããå©ç¨ã§ããããã
*2:glib.timeout_add_seconds()ãglib.timeout_add()ã®å¼æ°ã§ã¿ã¤ã ã¢ã¦ã颿°ã®å¼ã³åºãééã調æ´ã§ããç£è¦ã®ç´°ãã/夿´æã®åå¿ã®è¯ãã«é¢ä¿ãã¦ãã