python - How to make a Haskell suprocess called from Python to not close after one use?
问题描述
I have a simple .exe file compiled from Haskell that just prints to stdout everything it receives to stdin:
module Main where
main = do
command <- getLine
putStrLn command
main
And I have a Python file that tries to send two lines to the subprocess:
from subprocess import Popen, PIPE, STDOUT
p = Popen(['main.exe'], stdout=PIPE, stdin=PIPE, stderr=STDOUT)
def send_command(arg):
print("Sending command: "+arg)
response = p.communicate(input=arg)[0].decode()
print("Response: "+response+"\n")
return response
send_command("Test1")
send_command("Test2")
It works the first time around, but not the second, apparently because it considers the input completed:
Sending command: Test1
Response: Test1
main.exe: <stdin>: hGetLine: end of file
Sending command: Test2
Traceback (most recent call last):
File ".\test.py", line 12, in <module>
send_command("Test2")
File ".\test.py", line 7, in send_command
response = p.communicate(input=arg)[0].decode()
File "C:\Python27\lib\subprocess.py", line 483, in communicate
return self._communicate(input)
File "C:\Python27\lib\subprocess.py", line 722, in _communicate
self.stdin.write(input)
ValueError: I/O operation on closed file
I don't know if the fault lies with Python or Haskell; other subprocesses for as expected when called from Python, and the Haskell file works as expected when called from the command line, but they just refuse to work together. How to fix this?
Edit:
I replaced the communicate
with direct read\write:
from subprocess import Popen, PIPE, STDOUT
p = Popen(['main.exe'], stdout=PIPE, stdin=PIPE, stderr=STDOUT)
def send_command(arg):
print("Sending command: "+arg)
p.stdin.write(arg+"\n")
response = p.stdout.readline().decode()
print("Response: "+response+"\n")
return response
send_command("Test1")
send_command("Test2")
And made sure (just in case) that the .exe properly terminates lines:
module Main where
main = do
command <- getLine
putStrLn (command ++ "\n")
main
And now the program just stops and does nothing at this point:
Sending command: Test1
Am I supposed to somehow "flush" the input or what?
解决方案
Here is the documentation for the subprocess.Popen.communicate
function you're calling:
Popen.communicate(input=None, timeout=None)
Interact with process: Send data to stdin. Read data from stdout and stderr, until end-of-file is reached. Wait for process to terminate.
(my emphasis).
You can just write to p.stdin
and read from p.stdout
if you don't want all the other stuff communicate
does.
I don't know if the fault lies with Python or Haskell
This isn't intended as a criticism, but a helpful hint: the fault lies with whoever didn't read the documentation for the function they called. It's free, read it!
推荐阅读
- background - 如何复制 Squarespace 投资组合条目并保留背景图像?
- kubernetes - 带有需要作业的 initContainer 的水平 Pod 自动缩放 (HPA)
- flutter - 如何在flutter web中接收FCM推送通知数据并将用户重定向到通知中收到的链接?
- python - 当我尝试通过 windows powershell 在 docker 上运行部署 tensorflow 服务器时,收到“--mount”错误消息的“invalid argument”type=bind”
- java - Fastlane Screengrab - 不要在屏幕截图文件名中包含时间戳
- docker - 使用 docker 时出现问题,没有命令有效,“sudo”。怎么解决?
- python - DataLoader worker (pid(s) 5852, 3332, 1108, 5760) 意外退出
- android-studio - 最新更新后,Android Studio 无法在项目导航器中显示 cpp 文件
- express - axios 通过数据传递获取请求,但未正确传递数据
- java - Android Studio 警告整数乘法隐式转换为 long。如何解决这个问题?