我正在创建一个与Sphinx-Quickstart交互的程序。所以我想要做的是我的程序识别单词“path”然后输入一个特定的值。与其他人一样的情况,当我没有特定的单词时,只需输入一个输入('\ n')。我这样做是因为Sphinx有时会改变问题的顺序,如果我使用沟通,他们就会失败。
我想到这样的事情:
import subprocess
from subprocess import PIPE
p = subprocess.Popen('sphinx-quickstart', stdout=subprocess.PIPE, stderr=subprocess.STDOUT, stdin=PIPE, shell=True, bufsize=0)
p.stdin.write('doc\n')
a=p.stdout.readline()
print a.read()
while out:
line = out
line = line.rstrip("\n")
if "autodoc" in line:
pr = 1
p.stdin.write('y\n')
out = p.stdout.readline()
continue
if "source and build" in line:
pr = 2
p.stdin.write('y\n')
out = p.stdout.readline()
continue
out = p.stdout.readline()
p.stdin.close()
p.wait()
当我尝试读取输出时,我的程序挂起。
感谢您的提问
答案 0 :(得分:1)
您没有看到输出,因为您已重定向子流程的两个stdout / stderr。
您的程序挂起,因为sphinx-quickstart
等待您提供一些输入,例如,传递换行符以接受默认值,或者如果没有默认值则输入内容,例如,对于项目名称,作者值。
另一个原因是:
之后没有新行,sphinx-quickstart
在重定向stdout时不会及时刷新提示。
要解决此问题:一次读取一个字符而不是逐行读取,并使用python
选项运行-u
(或使用PYTHONUNBUFFERED
envvar)禁用缓冲。
每次在输出中看到提示行(以':'
char结尾)时,请确保脚本提供有效输入:
#!/usr/bin/env python
from __future__ import print_function
import os
from subprocess import Popen, PIPE, CalledProcessError
answers = {
'Root path': 'doc',
'source and build': 'y',
'autodoc': 'y',
'Project name': '<Project name>',
'Author name': '<author>',
'Project version': '<version>',
}
def iter_chunks(pipe, terminator_char):
"""Yield chunks from *pipe* that end with *terminator_char*."""
buf = []
for char in iter(lambda: pipe.read(1), ''):
buf.append(char)
if char == terminator_char:
yield ''.join(buf)
del buf[:]
if buf: # last chunk
yield ''.join(buf)
cmd = ['sphinx-quickstart']
p = Popen(cmd, stdin=PIPE, stdout=PIPE, universal_newlines=True, bufsize=0,
env=dict(os.environ, PYTHONUNBUFFERED='1'))
with p.stdin, p.stdout: # close pipes at the end
for chunk in iter_chunks(p.stdout, ':'):
line = chunk.rpartition('\n')[-1] # get last line
if line.lstrip().startswith('>') and line.endswith(':'): # found prompt
answer = next((a for q, a in answers.items() if q in line), '')
print(answer, file=p.stdin) #NOTE: short write is possible
if p.wait() != 0: # raise on non-zero exit status
raise CalledProcessError(p.returncode, cmd)
注意:stderr
未重定向
您还可以使用pexpect
模块与外部命令example进行类似对话的交互。
答案 1 :(得分:0)
不确定你想要什么,但这将运行并寻找正确的子串:
from subprocess import PIPE,Popen,STDOUT
p = Popen('sphinx-quickstart', stdout=PIPE, stderr=STDOUT, stdin=PIPE, universal_newlines=True)
p.stdin.write('doc\n')
for line in iter(p.stdout.readline, ""):
print(line.rstrip())
if "autodoc" in line:
pr = 1
p.stdin.write('y\n')
elif '"source" and "build"' in line:
pr = 2
p.stdin.write('y\n')
当你运行代码时,你会看到输出,源代码和构建都用引号括起来,所以你的if永远不会起作用。
for line in iter(p.stdout.readline, "")
会实时读取输出,取代你的while循环。
输出:
Welcome to the Sphinx 1.2.2 quickstart utility.
Please enter values for the following settings (just press Enter to
accept a default value, if one is given in brackets).
Enter the root path for documentation.
> Root path for the documentation [.]:
You have two options for placing the build directory for Sphinx output.
Either, you use a directory "_build" within the root path, or you separate
"source" and "build" directories within the root path.
> Separate source and build directories (y/n) [n]:
Inside the root directory, two more directories will be created; "_templates"
for custom HTML templates and "_static" for custom stylesheets and other static
files. You can enter another prefix (such as ".") to replace the underscore.