2016-11-14 84 views
1

我试图根据他给我的回答发送cmd许多命令。发送很多命令到cmd

我得到一个运行时错误信息:

ValueError: I/O operation on closed file 

当我跑步是这样的:

import subprocess 
process = subprocess.Popen("cmd.exe", stdout=subprocess.PIPE,stdin=subprocess.PIPE) 
answer = process.communicate(input="some command\n" + '\n')[0] 

""" 
choosing another command according to answer 
""" 

print process.communicate(input=another_command + '\n')[0] 
process.kill() 

就如何解决该问题的任何想法?

谢谢你的帮助!

+0

你能提供一个更大的图片吗?你在'process.kill()'之后发送你的命令吗?如果没有,你可以提供一些代码示例(使用真正的命令而不是'“某些命令”)? 您尝试在cmd中运行的命令有可能终止您的shell。 – woockashek

+0

即使没有'process.kill()',并且两个命令都是'“ipconfig \ n”'。第一个命令正在工作,第二个命令给我运行时错误 –

+0

执行一个命令可能会返回一个返回码,关闭Popen对象。例如,如果你执行ipconfig,那么执行'process.poll()'你可能会看到'0'的返回码。 – sytech

回答

1

不要将您的命令发送到cmd.exe。直接调用你的命令,如:

subprocess.Popen("dir", shell=True, stdout=subprocess.PIPE,stdin=subprocess.PIPE) 

也许你不会需要管道的标准输入,如果你这样使用它。

+0

如果我想用'sub-processing'和''''沟通()'来做到这一点,那可能吗?非常感谢您的帮助! –

+0

@EyalS您的任务是使用子处理和通信()或解决特殊问题? 你可以使用沟通管道输入到交互式命令。但我不认为你可以用它来将命令传递给cmd。 – jhinghaus

+0

由于某种原因,我的电脑无法识别cmd.exe作为系统程序,即使我的所有路径都完全正确,导致我试图绕过使用子处理的问题, –

0

错误是正常的。 communicate关闭子流程的标准输入以指示没有更多输入处于挂起状态,以便子流程可以刷新其输出。所以你不能在一个单独的子进程上链接多个communicate调用。

但是,如果您的命令足够简单(输入数据不是很多千字节),并且在发送下一个命令之前您不需要收集和处理一个命令的输出,则应该可以编写所有命令按顺序在它们中的两个之间读取尽可能多的输出。在最后一个命令后,您可以关闭子进程标准输入并等待它终止,仍然可以对输出进行整理:

process = subprocess.Popen("cmd.exe", stdout=subprocess.PIPE, stdin=subprocess.PIPE) 
process.stdin.write("some command\n\n") 
partial_answer = process.stdout.read() # all or part of the answer can still be buffered subprocess side 
... 
process.stdin.write("some other command\n\n") 
... 
# after last command, time to close subprocess 
process.stdin.close() 
retcode = None 
while True: 
    end_of_answer += process.stdout.read() 
    if retcode is not None: break 
+0

如果您没有使用专用阅读器线程,请注意发生死锁。在Windows中,您可以调用['PeekNamedPipe'](https://msdn.microsoft。com/en-us/library/aa365779)获取可用字节数,使用'msvcrt.get_osfhandle(process.stdout.fileno())'的句柄。这样你就不会发生死锁,试图读取更多可用的数据,而cmd.exe被阻止在等待stdin上的命令。要使用shell,您还可以设置自定义提示并一次读取一个字节,直到读取提示。 – eryksun

+0

另外,如果你不想重复调用'flush',并且cmd.exe需要结束行为'“\ r \ n”,那么通过'bufsize = 0'来防止缓冲'process.stdin' ,而不是'“\ n \ n”'。 – eryksun