'Capturing runpy.run_module stdout

I'm unable to capture stdout of runpy.run_module into a variable using StringIO.
To demonstrate the problem, I created a script called runpy_test.py (code below) using an arg switch;

  • 0 = do not redirect stdout.
  • 1 = redirect using StringIO, capture into variable, print variable.

Console Output

(base) PS C:\Users\justi\Documents> python .\runpy_test.py 0  
pip 20.0.2 from C:\ProgramData\Anaconda3\lib\site-packages\pip (python 3.6)  
(base) PS C:\Users\justi\Documents> python .\runpy_test.py 1  
(base) PS C:\Users\justi\Documents>  

I was expecting python .\runpy_test.py 1 to print pip 20.0.2 from C:\ProgramData\Anaconda3\lib\site-packages\pip (python 3.6), but as you can see from the above console capture, I'm getting nothing.

runpy_test.py

import io
import sys
import runpy
import copy

capture_stdout = bool(sys.argv[1] == "1")
if capture_stdout:
    _stdout = sys.stdout
    sys.stdout = io.StringIO()
_argv = copy.deepcopy(sys.argv)
sys.argv = ['', '-V']
runpy.run_module("pip", run_name="__main__")
sys.argv = _argv
if capture_stdout:
    result = sys.stdout.getvalue()
    sys.stdout = _stdout
    print(f"result: {result}")

I'm guessing sys.stdout is not being correctly re-initialised before I print because of something related to runpy.run_module, but not really sure how to debug. Any ideas would be great, solutions even better.
My environment is Python 3.6.10 using conda 4.8.3.
Thanks in advance.



Solution 1:[1]

Using subprocess.check_output instead of runpy.run_module solved my problem.
See Installing python module within code

Solution 2:[2]

You can use capsys in the pytest framework:

def test_main(capsys):
    runpy.run_module(
        "helloworld",
        init_globals=None,
        run_name="__main__",
        alter_sys=False)

    captured = capsys.readouterr()
    assert captured.out == "Hello, World!"

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 David A.