Skip to content

functools.partial(print, file=sys.stderr) stderr not captured via capsys/capfd #8900

Closed
@hroncok

Description

@hroncok

I've been wrapping my head around this for a while and I was unable to figure out what's going on and why my capsys (or capfd) usage does not capture stderr at all. I've narrowed the case down to using functools.partial(print, file=sys.stderr). When that function is used, its output is not captured in capsys.readouterr().err (or capsys.readouterr().err).

Here is a reproducer adapted from the docs:

import functools
import sys

def test_myoutput(capsys):
    print("hello")
    sys.stderr.write("world\n")
    captured = capsys.readouterr()
    assert captured.out == "hello\n"
    assert captured.err == "world\n"


def test_myoutput_all_prints(capsys):
    print("hello")
    print("world", file=sys.stderr)
    captured = capsys.readouterr()
    assert captured.out == "hello\n"
    assert captured.err == "world\n"


print_err = functools.partial(print, file=sys.stderr)


def test_myoutput_with_partial(capsys):
    print("hello")
    print_err("world")
    captured = capsys.readouterr()
    assert captured.out == "hello\n"
    assert captured.err == "world\n"


def test_myoutput_with_partial_capfd(capfd):
    print("hello")
    print_err("world")
    captured = capfd.readouterr()
    assert captured.out == "hello\n"
    assert captured.err == "world\n"

I'd expect all tests here to pass. The ones using print_err don't pass.

============================= test session starts ==============================
platform linux -- Python 3.9.6, pytest-6.2.4, py-1.10.0, pluggy-0.13.1
rootdir: /home/churchyard/tmp
collected 4 items

test_capsys.py ..FF                                                      [100%]

=================================== FAILURES ===================================
__________________________ test_myoutput_with_partial __________________________

capsys = <_pytest.capture.CaptureFixture object at 0x7f75539b6dc0>

    def test_myoutput_with_partial(capsys):
        print("hello")
        print_err("world")
        captured = capsys.readouterr()
        assert captured.out == "hello\n"
>       assert captured.err == "world\n"
E       AssertionError: assert '' == 'world\n'
E         - world

test_capsys.py:28: AssertionError
----------------------------- Captured stderr call -----------------------------
world
_______________________ test_myoutput_with_partial_capfd _______________________

capfd = <_pytest.capture.CaptureFixture object at 0x7f75538e0c40>

    def test_myoutput_with_partial_capfd(capfd):
        print("hello")
        print_err("world")
        captured = capfd.readouterr()
        assert captured.out == "hello\n"
>       assert captured.err == "world\n"
E       AssertionError: assert '' == 'world\n'
E         - world

test_capsys.py:36: AssertionError
----------------------------- Captured stderr call -----------------------------
world
=========================== short test summary info ============================
FAILED test_capsys.py::test_myoutput_with_partial - AssertionError: assert ''...
FAILED test_capsys.py::test_myoutput_with_partial_capfd - AssertionError: ass...
========================= 2 failed, 2 passed in 0.03s ==========================

The capsys/capfd captured standard error is empty. The printed "Captured stderr call" is populated instead.

My operating system is Fedora Linux. This is pip list:

Package    Version
---------- -------
attrs      21.2.0
iniconfig  1.1.1
packaging  21.0
pip        20.2.2
pluggy     0.13.1
py         1.10.0
pyparsing  2.4.7
pytest     6.2.4
setuptools 49.1.3
toml       0.10.2

But this also happens at least with pytest 6.0, 5.4 and 4.6.

Possibly related to #5997 but not sure.

Metadata

Metadata

Assignees

No one assigned

    Labels

    plugin: capturerelated to the capture builtin plugintype: questiongeneral question, might be closed after 2 weeks of inactivity

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions