通过流程多次沟通而不会破坏管道?

时间:2021-12-17 21:37:42

It's not the first time I'm having this problem, and it's really bugging me. Whenever I open a pipe using the Python subprocess module, I can only communicate with it once, as the documentation specifies: Read data from stdout and stderr, until end-of-file is reached

这不是我第一次遇到这个问题,这真的让我烦恼。每当我使用Python子进程模块打开管道时,我只能与它进行一次通信,如文档所指定的:从stdout和stderr读取数据,直到达到文件结尾

proc = sub.Popen("psql -h darwin -d main_db".split(),stdin=sub.PIPE,stdout=sub.PIPE)
print proc.communicate("select a,b,result from experiment_1412;\n")[0]
print proc.communicate("select theta,zeta,result from experiment_2099\n")[0]

The problem here is that the second time, Python isn't happy. Indeed, he decided to close the file after the first communicate:

这里的问题是,第二次,Python并不开心。实际上,他决定在第一次沟通后关闭文件:

Traceback (most recent call last):
File "a.py", line 30, in <module>
    print proc.communicate("select theta,zeta,result from experiment_2099\n")[0]
File "/usr/lib64/python2.5/subprocess.py", line 667, in communicate
    return self._communicate(input)
File "/usr/lib64/python2.5/subprocess.py", line 1124, in _communicate
     self.stdin.flush()
ValueError: I/O operation on closed file

Are multiple communications allowed?

是否允许多次通信?

4 个解决方案

#1


19  

I think you misunderstand communicate...

我觉得你误会了沟通......

http://docs.python.org/library/subprocess.html#subprocess.Popen.communicate

communicate sends a string to the other process and then waits on it to finish... (Like you said waits for the EOF listening to the stdout & stderror)

communication将字符串发送到另一个进程,然后等待它完成...(就像你说等待EOF听stdout和stderror)

What you should do instead is:

你应该做的是:

proc.stdin.write('message')

# ...figure out how long or why you need to wait...

proc.stdin.write('message2')

(and if you need to get the stdout or stderr you'd use proc.stdout or proc.stderr)

(如果你需要获取stdout或stderr,你可以使用proc.stdout或proc.stderr)

#2


4  

I've had this problem before, and as far as I could ever figure, you couldn't do this with subprocess (which, I agree, is very counterintuitive if true). I ended up using pexpect (obtainable from PyPI).

我以前遇到过这个问题,而且据我所知,你不能用子进程做这个(我同意,如果是真的话,这是违反直觉的)。我最终使用了pexpect(可从PyPI获得)。

#3


2  

You can use:

您可以使用:

proc.stdin.write('input')    
if proc.stdout.closed:
    print(proc.stdout)

#4


1  

You can do this simply with single call of communicate():

您可以通过单次调用communication()来完成此操作:

query1 = 'select a,b,result from experiment_1412;'
query1 = 'select theta,zeta,result from experiment_2099;'
concat_query = "{}\n{}".format(query1, query2)
print(proc.communicate(input=concat_query.encode('utf-8'))[0])

The key-point here is that you only write once to stdin, and \n serve as EOL. your psql subprocess reads from stdin until \n, then after it finishes the first query, it goes to stdin again, by which time only the second query string is left in the buffer.

这里的关键点是你只对stdin写一次,然后\ n作为EOL。你的psql子进程从stdin读取直到\ n,然后在完成第一个查询之后,再次进入stdin,此时只有第二个查询字符串留在缓冲区中。

#1


19  

I think you misunderstand communicate...

我觉得你误会了沟通......

http://docs.python.org/library/subprocess.html#subprocess.Popen.communicate

communicate sends a string to the other process and then waits on it to finish... (Like you said waits for the EOF listening to the stdout & stderror)

communication将字符串发送到另一个进程,然后等待它完成...(就像你说等待EOF听stdout和stderror)

What you should do instead is:

你应该做的是:

proc.stdin.write('message')

# ...figure out how long or why you need to wait...

proc.stdin.write('message2')

(and if you need to get the stdout or stderr you'd use proc.stdout or proc.stderr)

(如果你需要获取stdout或stderr,你可以使用proc.stdout或proc.stderr)

#2


4  

I've had this problem before, and as far as I could ever figure, you couldn't do this with subprocess (which, I agree, is very counterintuitive if true). I ended up using pexpect (obtainable from PyPI).

我以前遇到过这个问题,而且据我所知,你不能用子进程做这个(我同意,如果是真的话,这是违反直觉的)。我最终使用了pexpect(可从PyPI获得)。

#3


2  

You can use:

您可以使用:

proc.stdin.write('input')    
if proc.stdout.closed:
    print(proc.stdout)

#4


1  

You can do this simply with single call of communicate():

您可以通过单次调用communication()来完成此操作:

query1 = 'select a,b,result from experiment_1412;'
query1 = 'select theta,zeta,result from experiment_2099;'
concat_query = "{}\n{}".format(query1, query2)
print(proc.communicate(input=concat_query.encode('utf-8'))[0])

The key-point here is that you only write once to stdin, and \n serve as EOL. your psql subprocess reads from stdin until \n, then after it finishes the first query, it goes to stdin again, by which time only the second query string is left in the buffer.

这里的关键点是你只对stdin写一次,然后\ n作为EOL。你的psql子进程从stdin读取直到\ n,然后在完成第一个查询之后,再次进入stdin,此时只有第二个查询字符串留在缓冲区中。