- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我一直在使用 pyinotify,我遇到了一些问题,在对文件夹进行多次更改后,它只是停止接收通知。我觉得这与两个线程正在运行有关;即通知线程和wxpython线程。
该应用程序的目的基本上是在检测到 ip 连接时将图片加载到屏幕上,监控文件夹中的“ list ”文件,并根据该文件进行一些处理,即移动文件。
它间歇性地工作,但作为一个 python 新手,我不确定问题可能是什么,因为我基本上采用了线程示例并解决了它。有时,它只收到一个通知并停止接收文件更改通知。
此外,如果我重新启动 linux box 并重试,它可以处理大量文件更改,然后再次停止接收通知,这让我觉得它可能没有正确发布 watch ?
我们将不胜感激任何帮助,也非常欢迎进行优化和改进。我确信我可以从反馈中学到很多东西。代码如下
import pyinotify
import os.path
import shutil
import errno
import subprocess
import logging
import wx
import time
import signal
import sys
#update CHECKLIST name
CHECKLIST = 'Checklist' #this must exist in the update archive
#static values
DIR_UPDATE = 'd'
FILE_UPDATE = 'f'
PING_IP = ' localhost' # change in production
#paths
WATCH_PATH = '/home/test'
LOG_PATH = '/home/test/update.log'
CONNECTED_IMG = 'update.jpg'
UPDATING_IMG = 'updating.png'
#msgs
UPDATEFOUND_MSG = ' Update Found '
UPDATEUNZIPPEDSTART_MSG = ' Update unzipping '
UPDATEUNZIPPED_MSG = ' Update unzipped '
UPDATEFILE_MSG = ' Update file '
UPDATEFILEMSG_CONT = ' moved into path '
REMOVEFILEMSG_CONT = ' removed from update folder '
UPDATECOMPLETE_CONT = ' Update complete'
ROADANGELRESTART_MSG = ' Update restarting app '
DIRCREATED_MSG = ' Directory created at path '
#errors
UPDATEFAILED_MSG = ' Update process failed on '
BADLYFORMED_MSG = ' Badly formed src/dest combination '
UPDATESRCUNAVAILABLE = ' Invalid update file specified '
UPDATEDESTUNAVAILABLE = ' Invalid update destination specified '
INVALIDUPDATEFORMAT = ' Invalid format string '
#on startup create the watchfolder if it doesnt exist
WM = pyinotify.WatchManager() # Watch Manager
WM_MASK = pyinotify.IN_CLOSE_WRITE # watched events
#setup logger
LOGGER = logging.getLogger('Updater')
LOG_HANDLE = logging.FileHandler(LOG_PATH)
FORMATTER = logging.Formatter('%(asctime)s %(levelname)s %(message)s')
LOG_HANDLE.setFormatter(FORMATTER)
LOGGER.addHandler(LOG_HANDLE)
LOGGER.setLevel(logging.INFO)
#Global values used primarily in the main function loop
HANDLER = None
NOTIFIER = None
WDD = None
UPDATE_UI = None
WINDOW = None
CURR_IMG = None
LAST_CURRIMG = None
class EventHandler(pyinotify.ProcessEvent):
VERBOSE = False
""" Main class to monitor file events and process accordingly"""
def process_IN_CLOSE_WRITE(self, event):
""" Only executes when a Checklist has finished being written to"""
path = event.pathname
print 'evt'
#look for the update_ready file before processing
if (os.path.basename(path) == 'Checklist'):
EventHandler.parse_updates(WATCH_PATH)
global CURR_IMG
CURR_IMG = os.path.join(WATCH_PATH, UPDATING_IMG)
show_window()
print 'update completed'
time.sleep(1000)
@classmethod
def parse_updates(cls, path):
""" parses update files """
#handle errors for opening the file
file_path = os.path.join(path, CHECKLIST)
print file_path
files = open(file_path)
#handle errors for malformed tuples-done
#handle errors for unavailable files-done
#handle errors for unavailable dests-done #created automatically
#handle permission errors
for line in files:
#remove linebreaks etc and ensure its not empty
if line.strip():
array = line.split('=')
length = len(array)
if length == 3:
EventHandler.process_line(path, array)
else:
if length > 0:
EventHandler.print_bad_msg(array[0])
else:
EventHandler.print_bad_msg()
print 'removing ', file_path
os.remove(file_path) #remove the checklist file
@classmethod
def mkdir(cls, path):
""" makes a directory from a path"""
try:
os.mkdir(path)
print DIRCREATED_MSG, path
except OSError, err:
print err
if err.errno != errno.EEXIST: #thrown when the dir already exists
return False
@classmethod
def move_file(cls, src, dest):
""" moves a file from src to dest and remove after
expects that the dest already exists at this point
otherwise ignores the move"""
#print 'moving from', src, 'to ', dest
if os.path.isfile(dest):
shutil.copy2(src, dest)
else:
print UPDATEDESTUNAVAILABLE
#remove the src file when done
os.remove(src)
@classmethod
def process_line(cls, path, array):
""" process a line from the checklist"""
#remove newlines etc
update_file = array[0].strip()
update_src = os.path.join(path, update_file)
update_dest = array[1].strip()
update_type = array[2].strip()
#ensure we have valid values in all three fields
if update_file and update_dest and update_type:
#ensure the src file exists
if os.path.isfile(update_src):
#check if destination is directory and
#copy the file into the directory
if update_type == DIR_UPDATE:
EventHandler.mkdir(update_dest)
dest = os.path.join(update_dest, update_file)
EventHandler.move_file(update_src, dest)
else:
EventHandler.move_file(update_src, update_dest)
else:
print UPDATESRCUNAVAILABLE
else:
print INVALIDUPDATEFORMAT
@classmethod
def print_bad_msg(cls, msg = ''):
""" print a badly formed message with optional value"""
if msg:
print BADLYFORMED_MSG, msg
else:
print BADLYFORMED_MSG
class UpdateFrame(wx.Frame):
""" Displays update images to screen"""
def __init__(self, path):
wx.Frame.__init__(self, None, wx.ID_ANY)
image_file = path
image = wx.Bitmap(image_file)
image_size = image.GetSize()
# set the frame size to fit the screen size
self.SetClientSize(wx.DisplaySize())
# bitmap's upper left corner is in frame position (x, y)
# by default pos=(0, 0)
wx.StaticBitmap(self, wx.ID_ANY, image, size = image_size)
# the parent is the frame
self.SetTitle('Update Mode')
def ping_ip():
""" ping once to establish connection """
ret = subprocess.call("ping -c 1 %s" % PING_IP,
shell=True,
stdout=open('/dev/null', 'w'),
stderr=subprocess.STDOUT)
if ret == 0:
return True
else:
return False
def show_window():
""" update screen window when currimage changes is set """
global UPDATE_UI
global WINDOW
global CURR_IMG
global LAST_CURRIMG
if LAST_CURRIMG != CURR_IMG:
if not UPDATE_UI:
UPDATE_UI = wx.App()
if not WINDOW:
WINDOW = UpdateFrame(CURR_IMG)
UPDATE_UI.ExitMainLoop()
while(UPDATE_UI.IsMainLoopRunning()):
pass
WINDOW.Destroy()
WINDOW = UpdateFrame(CURR_IMG)
WINDOW.Show(True)
UPDATE_UI.MainLoop()
LAST_CURRIMG = CURR_IMG
print 'changed'
def in_updatemode():
return ping_ip()
while True:
try:
if not in_updatemode():
print 'waiting for connect'
time.sleep(3)
if NOTIFIER:
NOTIFIER.stop()
else:
if not HANDLER:
HANDLER = EventHandler()
if not NOTIFIER:
NOTIFIER = pyinotify.ThreadedNotifier(WM, HANDLER)
NOTIFIER.start()
if not WDD:
WDD = WM.add_watch(WATCH_PATH, WM_MASK, rec=True,quiet=False)
# ip is active so show the image and start the notifier
# state = ip active
CURR_IMG = os.path.join(WATCH_PATH, CONNECTED_IMG)
show_window()
print 'here'
except KeyboardInterrupt:
print 'out'
NOTIFIER.stop()
break
最佳答案
我基本上发现问题确实在于 pyinotify 的线程通知程序和 wxPython 的主循环不能很好地协同工作。
解决方案是创建一个自定义主循环(我一开始不知道您可以这样做)并将 pyinotify 的线程通知程序放置在该循环中。这样它就作为 wxPython 主循环的一部分运行。
下面的代码解释了这个概念
class CustomApp(wx.App):
def MainLoop(self):
global HANDLER
global WM
global NOTIFIER
global WDD
global UPDATE_UI
global PING_TIMER
# Create an event loop and make it active. If you are
# only going to temporarily have a nested event loop then
# you should get a reference to the old one and set it as
# the active event loop when you are done with this one...
evtloop = wx.EventLoop()
old = wx.EventLoop.GetActive()
wx.EventLoop.SetActive(evtloop)
# This outer loop determines when to exit the application,
# for this example we let the main frame reset this flag
# when it closes.
while self.keepGoing:
# At this point in the outer loop you could do
# whatever you implemented your own MainLoop for. It
# should be quick and non-blocking, otherwise your GUI
# will freeze.
# call_your_code_here()
if not HANDLER:
HANDLER = EventHandler()
if not WM:
WM = pyinotify.WatchManager() # Watch Manager
if not NOTIFIER:
NOTIFIER = pyinotify.ThreadedNotifier(WM, HANDLER)
NOTIFIER.start()
print 'notifier started'
if not WDD:
WDD = WM.add_watch(WATCH_PATH, WM_MASK, rec=True,quiet=False)
# This inner loop will process any GUI events
# until there are no more waiting.
while evtloop.Pending():
evtloop.Dispatch()
# Send idle events to idle handlers. You may want to
# throttle this back a bit somehow so there is not too
# much CPU time spent in the idle handlers. For this
# example, I'll just snooze a little...
time.sleep(0.10)
self.ProcessIdle()
wx.EventLoop.SetActive(old)
def OnInit(self):
global UPDATE_UI
if not UPDATE_UI:
UPDATE_UI = Updater()
UPDATE_UI.Show()
self.SetTopWindow(UPDATE_UI)
self.keepGoing = True
return True
"--------------------------------------------------------------------------------------"
Watcher()
app = CustomApp(False)
另外,我想在程序中捕获 SIGINT,我使用这个 url 中的方法解决了它 http://code.activestate.com/recipes/496735-workaround-for-missed-sigint-in-multithreaded-prog/
希望这对另一个 python 新手或老手有帮助:)
关于python - pyinotify 疑似线程问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7404389/
我刚拿到一台 iPad,就傻傻地拿到了 TexTouch 应用程序。愚蠢的是,由于 Apple 的规定,TexTouch 无法编译 Tex。它使用 Dropbox 将 .tex 文件同步到计算机。在远
我使用 pyinotify 来监控我的文件系统。问题是当我重命名目录并在重命名的目录中创建文件时,事件是从原始路径(由 event.name 引用)引发的。不知道哪里出了问题?初始化观察器时 add_
我想创建一个监视文件夹的模块。我写了一些代码: import os, pyinotify class FileWatcher: def start_watch(self, dir):
我正在使用 pyinotify(process_IN_MOVED 事件)来监视目录中出现的文件。当出现新文件时,会触发该事件,并对文件进行某种处理。问题是有时文件出现在目录中的速度比我处理它们的速度快
我一直在使用 pyinotify,我遇到了一些问题,在对文件夹进行多次更改后,它只是停止接收通知。我觉得这与两个线程正在运行有关;即通知线程和wxpython线程。 该应用程序的目的基本上是在检测到
我要 Pyinotify 观看具有子文件夹的模板目录,但我收到此错误: DIRECTORY /home/project/templates [Pyinotify ERROR] add_watch: c
可以将正则表达式与 inotify shell 命令一起使用,但不能与 pyinotify 一起使用。我可以使用正则表达式获取目录列表并将其传递给 add_watch,但是,文件夹“Do*”是动态的,
我对 asyncnotifier 的工作原理感到困惑。通知程序中到底线程化了什么?只有观察者线程吗?或者处理程序函数的每个回调都在其自己的线程上运行吗? 文档基本上没有提及该类的细节。 最佳答案 As
我知道 pyinotify.Notifier.check_events(self, timeout=None) 可能会超时 - 但我更喜欢它无限期地轮询。可以中断吗? 我正在调用 Notifier.s
我有一个 pyinotify 实例,它监视已安装的网络驱动器(使用 CIFS 安装)的 IN_WRITE_CLOSE 事件,如果服务器本身正常,它会完美地拾取系统创建的事件(sudo cp、sudo
有什么方法可以打印监视的文件修改吗?让我们举个例子:我正在监视 file.txt,Pyinotify 可以告诉我它已被修改,但它似乎无法输出发生了什么更改?我错了吗 ?如何查看我正在监视的文件发生了哪
这是一个奇怪的问题,strace 没有给我任何有用的信息。我正在使用 pyinotify 0.9.6 递归地监视目录,以便我可以将有关它的更改提交到 MySQL 数据库。问题是当我运行 pyinoti
每次修改某个文件时,我都尝试启动一个 python 脚本。准确地说,我在 Raspberry Pi 的串行端口上有一个设备,它将数据写入文本文件 (test.txt)。我已经尝试过这两种工具 - Wa
每次在某个目录中创建新文件时,我都想解析一个文件。为此,我正在尝试使用 pyinotify设置一个目录来监视 IN_CREATE 内核事件,并触发 parse() 方法。 这是模块: from pyi
我必须注意文件中当前内容的任何输入或所做的任何更改,在进行任何修改后,我需要运行位于同一文件夹中的 python 程序。 我尽力去理解,但我无法得到任何好的结果。如果有人可以帮助我解决这个问题,那将很
我正在尝试查看目录,并正在寻找文件修改。考虑使用 pyinotify。问题是,在使用 IN_MODIFY 事件检查文件更改时,如果我通过网络将一个 12 MB 的小文件复制到目录,它会触发相当多的事件
我在使用 pyinotify 时遇到问题:未调用 ProcessEvent 的方法 process_*() 代码 import sys, time, syslog from pyinotify imp
我是 python 的新手,我正在尝试使用 pygtk 将 pyinotify 与 GUI 界面结合使用。我有两个类,我的 gtk 类不做太多事情,只显示东西,还有一个处理监控的类。 当我分别运行它们
我有一个运行线程的 pyinotify 观察程序,称为一个单独的类,目前它只是在终端窗口中打印其发现,如果我希望我的脚本根据这些更改执行操作,我最好这样做: A) 使用每个通知修改数组 B)写入/tm
我正在使用 pyinotify 来监视文件夹以了解何时在其中创建文件。当创建某些文件时,我想移动它们。问题是文件一创建(很明显),我的程序就会尝试移动它,甚至在它完全写入磁盘之前。 有没有办法让 py
我是一名优秀的程序员,十分优秀!