如何让多个(python)进程监视一个文件夹中的项目,但一次只执行一个操作?

2024-09-29 17:18:14 发布

您现在位置:Python中文网/ 问答频道 /正文

假设我有一个python脚本,它监视一个文件夹中的新文件,然后根据某些条件(以文件名)处理这些文件(一次一个)

我需要同时运行几个“观察者”,这样他们就可以同时处理几个文件(渲染视频。)

一旦观察者拿起一个文件进行处理,它就会重命名它(在rendering_之前)

确保两个或更多的观察者不会同时获取同一个文件并尝试呈现同一个作业的最佳方法是什么

我唯一的想法是让每个“观察者”只在当前时间(以秒为单位)为x时进行检查,这样进程1就会在:01过一分钟时进行检查,等等。但这似乎很愚蠢,我们必须为每次检查等待整整一分钟

只是想澄清一下。。。假设我有4个运行watcher的实例。在监视文件夹中添加了7项:job1..job7。我要一个观察者接一份工作

当一个观察者完成后,它应该抓住下一个任务。所以watcher1可能做job1watcher2job2,等等

watcher1job1完成时,它应该选择job5

我希望这是清楚的

另外,我希望每个“观察者”在自己的终端窗口中运行,在那里我们可以看到它的进度,也可以轻松地终止或启动更多的观察者


Tags: 文件方法脚本文件夹视频文件名作业时间
2条回答

要展开我的评论,您可以尝试重命名文件,并通过每个观察者跟踪每个文件类型/名称,如下所示:

watcher 1 -> check for .step0 files
             rename to .step1 when finished
watcher 2 -> check for .step1 files
             rename to .step2 when finished
...
watcher n -> check for .step{n-1} files
             rename to .final_format when finished

为了演示,下面是一个使用multiprocessing实例化4个不同观察者的示例:

import time, glob
from multiprocessing import Process

path = 'Watcher Demo'

class Watcher(object):
    def __init__(self, num):
        self.num = num
        self.lifetime = 50.0

    def start(self):
        start = time.time()
        targets = '\\'.join((path, f'*.step{self.num-1}'))
        while time.time() - start <= self.lifetime:
            for filename in glob.glob(targets):
                time.sleep(2) # arificial wait so we can see the effects
                with open(filename, 'a') as file:                    
                    file.write(f"I've been touched inappropriately by watcher {self.num}\n")
                newname = glob.os.path.splitext(filename)[0] + f'.step{self.num}'
                glob.os.rename(filename, newname)

def create_file():
    for i in range(7):
        filename = '\\'.join((path, f'job{i}.step0'))
        with open(filename, 'w') as file:
            file.write(f'new file {i}\n')
        time.sleep(5)

if __name__ == '__main__':
    if not glob.os.path.exists(path):
        glob.os.mkdir(path)
    watchers = [Watcher(i).start for i in range(1, 5)]
    processes = [Process(target=p) for p in [create_file] + watchers]
    for proc in processes:
        proc.start()
    for proc in processes:
        proc.join()

它将创建和处理如下文件:

create_file()          -> *newfile*  -> job0.step0
Watcher(1).start()     -> job0.step0 -> job0.step1
watcher2('job0.step1') -> job0.step1 -> job0.step2
watcher3('job0.step2') -> job0.step2 -> job0.step3
watcher4('job0.step3') -> job0.step3 -> job0.step4

文件(如job0.step4)将按以下顺序进行:

new file 0
I've been touched inappropriately by watcher 1
I've been touched inappropriately by watcher 2
I've been touched inappropriately by watcher 3
I've been touched inappropriately by watcher 4

我没有将文件格式重命名为final格式,因为这只是一个演示,但是很容易实现,因为最终代码应该有不同的观察者,而不是通用的观察者

使用multiprocess模块,您将无法看到每个观察者的独立终端,但这只是为了演示这个概念。。。您可以随时切换到subprocess模块


作为一个补充,我确实注意到性能下降,而我正在测试这个。我想这是因为程序一直在循环和观看。一个更好、更有效的方法是将你的手表作为一项任务安排在特定的时间运行。你可以在点时每小时运行一次watch1,在15分钟时每小时运行一次watch2,在30分钟时每小时运行一次watch3。。。这是一种更有效的方法,因为它只查找一次文件,并且只在找到时处理它们

我认为你应该使用类似于多重处理的方法

你可以做的是有一个主程序,不断监视文件

然后当它检测到某个东西时,主程序将它发送给1个从程序并继续监视

因此,不是5个脚本在看,而是1个脚本在看,其余的脚本在看的脚本告诉他们时进行处理

你问我怎么做,我没有经验,这可能不是一个很好的方法:

为此,可以让主脚本将所需的数据临时存储在变量中。假设这个变量叫做“Data”

然后,如果在windows中要从主脚本运行,可以使用类似subprocess的方法:

subprocess.run(["python", "slave_file.py"])

然后您可以使用另一个python脚本(从属脚本),它执行以下操作:

from your_master_script import x

然后做事

相关问题 更多 >

    热门问题