I stumbled over the same issue recently. All output of subprocess only showed up once the command finished executing so thatI wrote this small fix for Windows for me:
import subprocess
import shlex
import os
from IPython.core.magic import register_line_magic
codepage_output = !chcp
print("Command output: >>" + codepage_output.s + "<<")
codepage_digits = "".join([d for d in codepage_output.s.split(":")[1] if d.isnumeric()])
print("Parsed Codepage: >>" + codepage_digits + "<<")
def run_windows_command(command, output_function=print):
print(f"=== Executing command: {command}")
process = subprocess.Popen(shlex.split(command), stdout=subprocess.PIPE, stderr=subprocess.STDOUT, env=os.environ.copy())
while True:
stdout_line = process.stdout.readline().decode(f"CP{codepage_digits}")
if not stdout_line:
break
else:
print(stdout_line.replace("\r\n", "\n")[:-1]) # Remove '\r\n' and '\n'
print(f"\n=== Command has finished")
@register_line_magic
def cmd_unbuffered(line):
line_with_resolved_vars = line.format(**globals(), **locals())
return run_windows_command(line_with_resolved_vars)
Now you can write something like this in a cell:
%cmd_unbuffered PING 127.0.0.1 -n 1
I have only scratched on the surface of the documenation, I am sure that there is a more elegant way of doing in. Additionally, this does not check for Linux and assumes that everything works like under Windows, e.g. the command chcp
.