Python:等效于使用sys.stdin的输入 [英] Python: equivalent of input using sys.stdin
问题描述
我想测试一些直接使用print
和input
函数的(python 3)代码.据我了解,最简单的方法是依赖注入:修改代码,使其将输入和输出流作为参数,默认情况下使用sys.stdin
和sys.stdout
,并在测试过程中传递模拟对象.很明显,如何处理print
调用:
I want to test some (python 3) code that directly uses the print
and input
functions. As I understand it, the easiest way to do this is by dependency injection: modifying the code so that it takes input and output streams as arguments, using sys.stdin
and sys.stdout
by default and passing in mock objects during testing. It's obvious what to do with print
calls:
print(text)
#replaced with...
print(text, file=output_stream)
但是,input
没有用于输入和输出流的参数.以下代码是否正确地重现其行为?
However, input
doesn't have arguments for input and output streams. Does the following code correctly reproduce its behaviour?
text = input(prompt)
#replaced with...
print(prompt, file=output_stream, end='')
text = input_stream.readline()[:-1]
我看了input
的实现,它做了很多魔术,调用sys.stdin.fileno
并检查sys.stdin.encoding
和sys.stdin.errors
而不是调用任何read*
方法-我不会不知道从哪里开始嘲笑那些.
I had a look at the implementation of input
, and it does quite a lot of magic, calling sys.stdin.fileno
and examining sys.stdin.encoding
and sys.stdin.errors
rather than calling any of the read*
methods - I wouldn't know where to start with mocking those.
推荐答案
input()
仅在未更改stdin
和stdout
时提及的魔术,因为只有这样,它才能使用readline库之类的功能.如果您将它们替换为其他文件(是否为真实文件),它将归结为以下代码:
input()
only does the magic you mentioned when stdin
and stdout
are not altered, because only then it can use things like the readline library. If you replace them with something else (real-files or not) it comes down to this code:
/* Fallback if we're not interactive */
if (promptarg != NULL) {
if (PyFile_WriteObject(promptarg, fout, Py_PRINT_RAW) != 0)
return NULL;
}
tmp = _PyObject_CallMethodId(fout, &PyId_flush, "");
if (tmp == NULL)
PyErr_Clear();
else
Py_DECREF(tmp);
return PyFile_GetLine(fin, -1);
PyFile_GetLine
readline
方法.因此,嘲讽sys.std*
将起作用.
建议您使用try: finally:
,上下文处理器或mock
模块来执行此操作,以便即使正在测试的代码因异常而失败,也可以恢复输出:
It's recomended you do this with try: finally:
, a context processor or the mock
module, so that the outputs are restored even if the code you are testing fails with exceptions:
from unittest.mock import patch
from io import StringIO
with patch("sys.stdin", StringIO("FOO")), patch("sys.stdout", new_callable=StringIO) as mocked_out:
x = input()
print("Read:", x)
assert mocked_out.getvalue() == "Read: FOO\n"
这篇关于Python:等效于使用sys.stdin的输入的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!