我在Windows 2012服务器上使用Python监视程序模块来监视共享驱动器上出现的新文件。当看门狗注意到新文件时,它将启动数据库恢复过程。
但是,监视程序似乎会尝试在创建第二个文件时恢复文件,而不是等到文件完成复制到共享驱动器。所以我将事件更改为on_modified,但有两个on_modified事件,一个是最初复制文件时的事件,另一个是复制完成后的事件。
如何将两个on_modified事件处理为仅在复制到共享驱动器的文件结束时触发?
将多个文件同时复制到共享驱动器会发生什么?
这是我的代码
import time
import subprocess
from watchdog.observers import Observer
from watchdog.events import FileSystemEventHandler
class NewFile(FileSystemEventHandler):
def process(self, event):
if event.is_directory:
return
if event.event_type == 'modified':
if getext(event.src_path) == 'gz':
load_pgdump(event.src_path)
def on_modified(self, event):
self.process(event)
def getext(filename):
"Get the file extension"
file_ext = filename.split(".",1)[1]
return file_ext
def load_pgdump(src_path):
restore = 'pg_restore command ' + src_path
subprocess.call(restore, shell=True)
def main():
event_handler = NewFile()
observer = Observer()
observer.schedule(event_handler, path='Y:\\', recursive=True)
observer.start()
try:
while True:
time.sleep(1)
except KeyboardInterrupt:
observer.stop()
observer.join()
if __name__ == '__main__':
main()
答案 0 :(得分:5)
在on_modified事件中,只需等待文件完成复制,即可通过观察文件大小。
提供更简单的循环:
option description
mar numerical vector indicating margin size c(bottom, left, top, right) in lines. default = c(5, 4, 4, 2) + 0.1
mai numerical vector indicating margin size c(bottom, left, top, right) in inches
pin plot dimensions (width, height) in inches
答案 1 :(得分:1)
我会添加评论,因为这不是您问题的答案,而是一种不同的方法......但我还没有足够的代表。您可以尝试监视filesize,如果它停止更改,您可以假设副本已完成:
copying = True
size2 = -1
while copying:
size = os.path.getsize('name of file being copied')
if size == size2:
break
else:
size2 = os.path.getsize('name of file being copied')
time.sleep(2)
答案 2 :(得分:1)
我最近与看门狗有类似的问题。一个相当简单但不是非常聪明的解决方法是我使用两个元素列表检查文件大小的变化,一个用于过去'一个用于'现在' 。一旦值相等,复制就完成了。
编辑:类似这样。
past = 0
now = 1
value = [past, now]
while True:
# change
# test
if value[0] == value[1]:
break
else:
value = [value[1], value[0]]
答案 3 :(得分:1)
我正在使用以下代码等到复制文件(仅适用于Windows):
from ctypes import windll
import time
def is_file_copy_finished(file_path):
finished = False
GENERIC_WRITE = 1 << 30
FILE_SHARE_READ = 0x00000001
OPEN_EXISTING = 3
FILE_ATTRIBUTE_NORMAL = 0x80
if isinstance(file_path, str):
file_path_unicode = file_path.decode('utf-8')
else:
file_path_unicode = file_path
h_file = windll.Kernel32.CreateFileW(file_path_unicode, GENERIC_WRITE, FILE_SHARE_READ, None, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, None)
if h_file != -1:
windll.Kernel32.CloseHandle(h_file)
finished = True
print 'is_file_copy_finished: ' + str(finished)
return finished
def wait_for_file_copy_finish(file_path):
while not is_file_copy_finished(file_path):
time.sleep(0.2)
wait_for_file_copy_finish(r'C:\testfile.txt')
我的想法是尝试使用共享读取模式打开文件进行写入。如果其他人正在写信,它将失败。
享受;)
答案 4 :(得分:1)
老我知道,但我最近想出了这个确切问题的解决方案。就我而言,我只关心 wav 和 mp3 文件。此函数将确保只有完全复制的文件才会发送到 makerCore(),因为创建的占位符文件没有任何扩展名,并且始终以“未准备好”结尾。一旦文件完成,它将再次触发看门狗模块,但这次带有扩展名。这也可以同时处理多个文件。
def on_created(event):
#print(event)
if str(event.src_path).endswith('.mp3') or str(event.src_path).endswith('.wav'):
makerCore(event)
else:
print('not ready')
答案 5 :(得分:0)
我使用的方法可能不是最优雅的方法,但如果您可以控制复制文件,那么在任何平台上都可以轻松完成。
刚刚进行中&#39;到复制完成之前的文件名,然后重命名该文件。然后,您可以使用while循环等待名称没有&#39;正在进行中的文件。存在,你很好。
答案 6 :(得分:0)
这对我有用。在python3.7中也在Windows中进行了测试
while True:
size_now = os.path.getsize(event.src_path)
if size_now == size_past:
log.debug("file has copied completely now size: %s", size_now)
break
# TODO: why sleep is not working here ?
else:
size_past = os.path.getsize(event.src_path)
log.debug("file copying size: %s", size_past)
答案 7 :(得分:0)
我已经尝试过检查文件大小-等待-再次检查上面许多建议的例程,但这不是很可靠。为了使它更好地工作,我添加了一个检查文件是否仍然被锁定。
file_done = False
file_size = -1
while file_size != os.path.getsize(file_path):
file_size = os.path.getsize(file_path)
time.sleep(1)
while not file_done:
try:
os.rename(file_path, file_path)
file_done = True
except:
return True