Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

python pytest occasionally fails with OSError: reading from stdin while output is captured

While running a particular unittest with pytest, it occasionally fails with this error (mentioned in the title) and from the stack trace it happens on the line

choice = input().lower()

when the control reaches this statement, the entire function is:

def prompt_to_activate(bear, printer):
    PROMPT_TO_ACTIVATE_STR = ('program has found {} to be useful '
                              'based of dependencies discovered from your '
                              'project files. \n Would you like to activate '
                              'it? (y/n)')
    printer.print(PROMPT_TO_ACTIVATE_STR)

    choice = input().lower()

    if choice.startswith('y'):
        return True
    elif choice.startswith('n'):
        return False
    else:
        return prompt_to_activate(bear, printer)
for i in range(0, 3):
    a = i
print(a)

I tried adding some time.sleep(x) before that statement but that wouldn't fix it. Can somebody tell me the exact reason why this is happening and how to fix it?

like image 874
Ishan Srivastava Avatar asked Jul 18 '18 02:07

Ishan Srivastava


People also ask

How to read data from stdin in Python?

There are three ways to read data from stdin in Python. 1. Using sys.stdin to read from standard input Python sys module stdin is used by the interpreter for standard input. Internally, it calls the input () function. The input string is appended with a newline character ( ) in the end. So, you can use the rstrip () function to remove it.

How does pytest capture file level data?

There are three ways in which pytest can perform capturing: fd (file descriptor) level capturing (default): All writes going to the operating system file descriptors 1 and 2 will be captured. sys level capturing: Only writes to Python files sys.stdout and sys.stderr will be captured. No capturing of writes to filedescriptors is performed.

What is oserror in Python?

OSError is a built-in exception in Python and serves as the error class for the os module, which is raised when an os specific system function returns a system-related error, including I/O failures such as “file not found” or “disk full”. Below is an example of OSError: Attention geek!

How to run automated pytest with user input?

Automated tests shouldn't require user input that interrupts the test run; use command line arguments or environment variables for passing user input. Show activity on this post. try to extract the functions into a separate file, call them in the file and run the pytest with the -s flag like this pytest FILENAME -s


3 Answers

In case someone else stumbles upon this, this error will also be raised if you forgot a pdb breakpoint (import ipdb; ipdb.set_trace()) in your code.

like image 61
Tom Bug Avatar answered Sep 22 '22 13:09

Tom Bug


Since input() is an interactive function, you'll want to mock out the return value in your automated tests. Something like this:

def test_prompt(capsys, monkeypatch):
    monkeypatch.setattr('path.to.yourmodule.input', lambda: 'no')
    val = prompt_to_activate(bear=..., printer=...)
    assert not val
like image 32
wim Avatar answered Sep 22 '22 13:09

wim


You might also receive this if you set a breakpoint, but didn't use the -s flag with pytest.

like image 23
Joshua Cook Avatar answered Sep 20 '22 13:09

Joshua Cook