Python2:在子进程中暂停或使用yield,并从另一个进程中获取值

2024-09-30 04:32:01 发布

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

我正在使用python3编写一个程序(假设下面的main.py是在python3中运行的)并使用一个现有的python扩展(用c编写,用python2编译),我没有用于该扩展的源代码。假设FrozenModule类来自此扩展。它确实做了很多事情,但只是试图在这里简化它。基本上我可以订阅它的事件,我真的可以控制回调函数。这意味着我可以通过更新回调函数来更改流

问题是我必须重新组织流,并且希望在每次调用回调函数时冻结/暂停

我想要的最终结果是:

1:a,i,x
5:b,j,y
8:c,k,z

这就是我现在得到的,代码如下。但这并不是我想要的方式。我添加了set_trace只是为了检查流。我得到正确输出的原因是因为我已经在func2.pyfunc3.py中定义了SELECTED值。实际上,我希望这个来自func1.py

简而言之,我真的希望func1.py首先运行,从中获取特定的键,然后运行func2.py,它基本上遍历它所拥有的数据,直到它命中该事件/键,然后执行回调。暂停,对func3.py执行相同的操作,然后也暂停。然后回到func1.py并重新做一遍

目前它的工作方式(不是下面的代码,而是我正在重写的当前程序),它首先运行整个func1.py,然后所有键都是已知的,然后传递给func2.pyfunc3.py,然后我们分别得到值。最后,将其全部附加在一起以生成整个表,如下所示:

1:a,i,x
5:b,j,y
8:c,k,z

主要的问题是这些工作非常大,可能需要很长时间。它也可能在中间崩溃,在那里用户不会得到任何东西。因此,新方法是逐行或逐行生成最终输出。而不是每列执行一列,然后组合所有内容并将整个结果提供给用户

下面代码的问题是,当我运行子流程时(之所以使用子流程是因为扩展只需要在python2中),它实际上会立即运行/迭代整个数据。我在文件中添加了写操作,只是为了确保这一点。因此,只要运行main.py,甚至不点击'c'继续设置跟踪,f2.txt就已经有了:

1,i
5,j
8,k

最初它应该是空的,然后当我在main中点击'c'时,它应该只写一行,暂停,然后等待下一行。当然,set_跟踪和写入文件只是为了测试

简而言之,主要目标是逐行写入输出。两个主要问题是:1)如何在每次调用回调时暂停子进程。2) 将从func1.py获得的值传递给func2.pyfunc3.py,然后继续/取消暂停进程

抱歉发了这么长的邮件。此外,我希望我的问题是明确的

示例代码如下所示:

在main.py中

import subprocess


class ProcReader():
    def __init__(self, python_file):
        self.proc = subprocess.Popen(['python2', python_file], stdout=subprocess.PIPE)

    def __iter__(self):
        return self

    def __next__(self):
        while True:
            line = self.proc.stdout.readline()
            if not line:
                raise StopIteration
            return line


r1 = ProcReader("func1.py")
r2 = ProcReader("func2.py")
r3 = ProcReader("func3.py")


for l1, l2, l3 in zip(r1, r2, r3):
    d1 = l1.decode('utf-8').strip().split(",")
    d2 = l2.decode('utf-8').strip().split(",")
    d3 = l3.decode('utf-8').strip().split(",")
    print(f"{d1[0]}:{d1[1]},{d2[1]},{d3[1]}")
    import pdb
    pdb.set_trace()

在func1.py中

from frozenmodule import FrozenModule

def callback(k, v):
    with open("f1.txt", 'a') as f:
        print(f"{k},{v}")
        f.write(f"{k},{v}\n")
        fm.match = next(iter_items, None)
        # somehow pause here, maybe use yield?


SELECTED = [1, 5, 8]
FAKE_DATA = {1: 'a',
             5: 'b',
             8: 'c'}
iter_items = iter(SELECTED)
fm = FrozenModule(FAKE_DATA, callback)
fm.match = next(iter_items, None)
fm.run()

在func2.py中

from frozenmodule import FrozenModule

def callback(k, v):
    with open("f2.txt", 'a') as f:
        print(f"{k},{v}")
        f.write(f"{k},{v}\n")
        # somehow pause here, maybe use yield?
        # then get value from func1.py and set to fm.match
        fm.match = next(iter_items, None)



SELECTED = [1, 5, 8]
FAKE_DATA = {1: 'i',
             5: 'j',
             8: 'k'}
iter_items = iter(SELECTED)
fm = FrozenModule(FAKE_DATA, callback)
fm.match = next(iter_items, None)
fm.run()

在func3.py中

from frozenmodule import FrozenModule

def callback(k, v):
    with open("f3.txt", 'a') as f:
        print(f"{k},{v}")
        f.write(f"{k},{v}\n")
        # somehow pause here, maybe use yield?
        # then get value from func1.py and set to fm.match
        fm.match = next(iter_items, None)
        


SELECTED = [1, 5, 8]
FAKE_DATA = {1: 'x',
             5: 'y',
             8: 'z'}
iter_items = iter(SELECTED)
fm = FrozenModule(FAKE_DATA, callback)
fm.match = next(iter_items, None)
fm.run()

在frozenmodule.py中

class FrozenModule():
    def __init__(self, fake_data, callback):
        self.fake_data = fake_data
        self.match = 0
        self.callback = callback

    def run(self):
        for x in range(10):
            if x == self.match:
                self.callback(x, self.fake_data[x])

Tags: pyselfnonedefmatchcallbackitemsnext

热门问题