关于python:只有在没有其他“进程”正在处理的情况下才能读取文件

Reading a file, only if no other 'process' is working on it

我想打开3个PowerShell并在其中3个上运行相同的代码,只是不同的文件。因为它们的逻辑完全相同,所以它们中的每一个都会尝试访问彼此的文件,以检查是否有写入的内容process1有client1.txt,process2有client2.txt,process3有client3.txt下面是一些代码,说明在选择要处理的问题之前,流程3应该检查哪些问题:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
import os
while True:
f = 'C:\Users\Files'
i = {}
i['word'] = 'problem X' #just an example, I'll have a whole list
if os.path.exists(f):
    try:
        os.rename(f, f)
        print 'Access on file"' + f +'" is available!'
        file1 = open('C:\Users\Files\client1.txt', 'r+')
        file2 = open('C:\Users\Files\client2.txt', 'r+')
        if file1.read() == i['word']:
            print"A process is already working on this problem, check another"
        elif file2.read() == i['word']:
            print"A process is already working on this problem, check another"
        else:
            print"Found a new problem to work on"
            file3 = open('C:\Users\Files\client3.txt', 'r+')
            file3.write(i['word'])
            file1.close()
            file2.close()
            file3.close()

    except OSError as e:
        print 'Access-error on file"' + f + '"!
'
+ str(e)
        time.sleep(5)
        pass

我试图通过代码来表示的是:我只希望在其他人还没有解决问题的情况下启动一个进程,因为他们都有相同的逻辑,他们会试图解决相同的问题(我有很多需要解决的问题),因此他们可能会在程序继续使用while True的同时到达。当问题解决后,它将删除文件的内容并选择一个新问题,然后将它正在处理的问题写入自己的文件中,供其他人稍后检查。

只是要澄清一点:假设process1首先发现了一个问题("a a a"),它们都有空的txt文件,它会检查txt2和txt3,并看到它不等于("aaa"),然后它会将其写入自己的文件并关闭它。我想让process2在一秒钟后读取txt1和txt3,并看到("a a a")已经开始工作,它将得到列表中的下一个并再次检查,确保("bbb")正常,并且它将写入自己的文件。当它结束时,它从txt中删除字符串并开始查找另一个字符串。

这两个进程在试图同时检查文件时也存在问题。如果有一种方法可以将一个time.sleep()放到一个进程中,如果另一个进程正在使用该文件,然后稍后再试?


理想情况下,您将使用Python的多处理模块来启动每个进程。您可以让一个进程监视新文件,并将它们送入工作进程读取的队列。此解决方案将消除任何文件锁定的需要,因为只有一个进程在查找新文件。

但是,如果必须通过PowerShell启动进程,则必须使用某种类型的锁来使进程协同工作。真正的文件锁定很难以跨平台的方式进行。不过,你可以用move来伪装它。例如,您可以尝试移动文件(假设您要移动到同一文件系统上的某个位置,那么在大多数操作系统上,移动是原子的)。如果移动失败,您知道另一个进程必须先到达它,或者操作系统出了严重的问题。然后,您可以对移动的文件执行所有处理。例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import path
import shutil

filename ="C:\\path\\to\\filename.txt"
_filename = os.path.join(os.path.basename(filename),".wip")
wip_filename = os.path.join(os.path.dirname(filename), _filename)

try:
    shutil.move(filename, wip_filename)
except OSError:
    # another process moved it first
    pass
else:
    do_work(wip_filename)