添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

Popen.communicate引发ValueError:'对已关闭文件的I/O操作'。

0 人关注

I get the following error when I run my code.

Uncaught exception <class 'ValueError'>: I/O operation on closed file.Traceback (most recent call last): File "/home/gidumah/miniconda/envs/ytune/lib/python3.7/runpy.py", line 193, in _run_module_as_main "__main__", mod_spec) File "/home/gidumah/miniconda/envs/ytune/lib/python3.7/runpy.py", line 85, in _run_code exec(code, run_globals) File "/home/gidumah/ytopt/ytopt/ytopt/search/ambs.py", line 128, in <module> search.main() File "/home/gidumah/ytopt/ytopt/ytopt/search/ambs.py", line 105, in main results = list(self.evaluator.get_finished_evals()) File "/home/gidumah/ytopt/ytopt/ytopt/evaluator/evaluate.py", line 200, in get_finished_evals y = future.result() File "/home/gidumah/ytopt/ytopt/ytopt/evaluator/subprocess_evaluator.py", line 41, in result stdout, stderr_data = self.proc.communicate() File "/home/gidumah/miniconda/envs/ytune/lib/python3.7/subprocess.py", line 951, in communicate stdout = self.stdout.read() ValueError: I/O operation on closed file.

我所运行的代码是 subprocess_evaluator.py ,下面给出了这个代码。

class PopenFuture:
    FAIL_RETURN_VALUE = Evaluator.FAIL_RETURN_VALUE
    def __init__(self, args, parse_fxn):
        self.proc = subprocess.Popen(args, shell=True, stdout=subprocess.PIPE,
                                     stderr=subprocess.STDOUT, encoding='utf-8')
        self._state = 'active'
        self._result = None
        self._parse = parse_fxn
    def _poll(self):
        if not self._state == 'active':
            return
        retcode = self.proc.poll()
        if retcode is None:
            self._state = 'active'
            stdout, stderr_data = self.proc.communicate()
            tmp_res = self._parse(stdout)
            if tmp_res != sys.float_info.max:
                self._result = tmp_res
        elif retcode == 0:
            self._state = 'done'
        else:
            self._state = 'failed'
    def result(self):
        if self._result is not None:
            return self._result
        self.proc.wait()
        stdout, stderr_data = self.proc.communicate()
        if self.done:
            self._result = self._parse(stdout)
        else:
            self._result = self.FAIL_RETURN_VALUE
            logger.error(f"Eval failed: {stdout}")
        # if stdout:
        #     print (stdout)#.split('\n')[:-2])#)[:-1])
        return self._result

它说错误是在第41行,该行的内容是:stdout, stderr_data = self.proc.communicate()

我在沟通电话方面是否有什么地方做得不对?

1 个评论
今后,请将代码和回溯粘贴为纯文本,周围有````代码标签,而不是什么IDE选项,它产生的HTML格式,我不得不手动删除。
python
io
subprocess
valueerror
user17392162
user17392162
发布于 2022-06-30
1 个回答
Pawel Kam
Pawel Kam
发布于 2022-07-01
已采纳
0 人赞同

根据 文件 :

Popen. 传达 (input=None, timeout=None)

与进程互动。 发送数据到stdin。从stdout和stderr读取数据,直到 直到达到文件的终点。等待进程终止并设置 returncode属性。可选的输入参数应该是要发送给子进程的数据 发送给子进程的数据,或者如果不需要发送数据给子进程,则为None。 子进程。如果流是以文本模式打开的,输入必须是一个字符串。 否则,它必须是字节。

请注意,它在等待进程的终止。因此, Popen.communicate 不能被多次运行。在 Popen.communicate 的上下文中的错误意味着程序已经终止了进程并关闭了管道,并在第二次调用 communicate 时引发了异常。

看来你使用的代码是 ytopt library .请检查你是否正确使用该代码,注意它在几个不同的地方调用了 communicate() ,有时会传递ValueErrors,但有时不会。另外,请查看Thomas Wouters solution to the problem:

If you want to use 传达, you have to either restart the process in the loop, or give it a single string that is all the input from the generator. If you want to do streaming communication, sending data bit by bit, then you have to not use 传达. Instead, you would need to write to p.stdin while reading from p.stdout and p.stderr. Doing this is tricky, because you can't tell which output is caused by which input, and because you can easily run into deadlocks. There are third-party libraries that can help you with this, like Twisted.

如果你想以交互的方式做这件事,发送一些数据,然后 等待和处理结果,然后再发送更多的数据,事情就会变得更加困难。 变得更加困难。你可能应该使用一个第三方库,如 pexpect这样的第三方库。

当然,如果你能在循环中启动这个过程,那就容易多了。 循环,那会容易得多。

cmd = ['intersectBed', '-a', 'stdin', '-b', bedfile]
for entry in my_entry_generator: