【问题标题】:How should I have one process blocked until another process writes a line to a file?我应该如何阻止一个进程,直到另一个进程将一行写入文件?
【发布时间】:2014-12-23 21:12:45
【问题描述】:

我有一个进程(agxp)接收数据并将它们写入一个文件,另一个进程将数据发送到另一个进程。

当 agxp 启动时,它应该会立即产生一些输出。我希望主进程阻塞,直到它在文件中看到 agxp 输出的第一行。

我正在通过比较文件的状态来检查第一行是否已写入文件,但它们总是相同的。所以我陷入了while循环。为什么会这样?

        rvListen_AGX =  "tibrvlisten -service " + agxService  + " -network " + agxNetwork + " -daemon " + domain

        agxf = open(self.AGX_logFileName, 'w')
        agxstat = os.stat(self.AGX_logFileName)
        agxp = subprocess.Popen(rvListen_AGX.split(), stdout = agxf, bufsize=0)


        while os.stat(self.AGX_logFileName) == agxstat:
            print agxstat
            print os.stat(self.AGX_logFileName)
            stxf.flush()
            sleep(0.1)

【问题讨论】:

  • 您可以在主进程中设置stdout=PIPE并写入agxf

标签: python-2.7 subprocess


【解决方案1】:

等到子进程将一行写入其标准输出并将子进程的标准输出保存到文件中:

import shutil
from subprocess import Popen, PIPE
from threading import Thread

def copy_and_close(source, destination):
    with source, destination:
        shutil.copyfileobj(source, destination)

agx_cmd = ("tibrvlisten -service {agxService} -network {agxNetwork} "
           "-daemon {domain}".format(**vars())).split()
agx_process = Popen(agx_cmd, stdout=PIPE, bufsize=1)
agx_file = open(self.AGX_logFileName, 'wb')
agx_file.write(agx_process.stdout.readline()) # block until a line is read
Thread(target=copy_and_close, args=[agx_process.stdout, agx_file]).start()
# do other things here..
rc = agx_process.wait()

如果您在agx_process 运行时不需要做其他事情,那么您可以在主线程中调用copy_and_close()

【讨论】:

  • 我喜欢你的想法,但它并没有真正回答我的问题。我问的是为什么我的代码卡在 while 循环中,而不是如何解决问题。
  • @user1559897:我已经回答了标题中的“如何”。 while-loop 的含义取决于平台和文件系统设置,例如,st_mtime 更新可能会延迟到文件缓存刷新。
【解决方案2】:

我认为你需要的是进程同步机制。您可以使用多种原语来实现相同的目的。例如,Lock 用于锁定资源,以便其他进程在一个进程使用它时无法访问它。同样,Mutex 和 semaphore 也有同样的用途。

我为您提供了一个来自 python doc 的示例,它可以帮助您了解如何实现它。

from multiprocessing import Process, Lock

def f(l, i):
    l.acquire()
    print 'hello world', i
    l.release()

if __name__ == '__main__':
    lock = Lock()

    for num in range(10):
        Process(target=f, args=(lock, num)).start()

在上面的示例中,您可以看到有一个邮件进程将创建 10 个其他进程。在这里,主进程将锁(由它创建)传递给每个进程,因此每个进程都获得相同的锁。现在每个进程都会在执行实际任务之前尝试获取锁。由于它是相同的锁(在进程之间共享),因此一次只有一个进程能够获取锁,因此其他进程将等到第一个进程释放锁。

如果您的两个进程不是从主进程派生出来的(就像完全是两个不同的进程独立派生),那么您需要实现全局共享内存或全局互斥体或全局信号量。

【讨论】:

  • 它是关于使用multiprocessing 创建的子进程。它对 OP 的 subprocess.Popen()-created 子进程有何帮助?
猜你喜欢
  • 2021-08-20
  • 2012-07-05
  • 1970-01-01
  • 2020-09-27
  • 1970-01-01
  • 2012-01-06
  • 1970-01-01
  • 2016-12-29
  • 1970-01-01
相关资源
最近更新 更多