1

When I run a python module with asyncio, it works as intended when executed from cmd, but not when executed from git bash.

The code is intended to print "hello", wait 3 seconds, then print "world". It does this correctly in cmd, but in git bash, it waits three seconds first, and then prints both statements back to back.

Here is the code:

import asyncio

async def main():
    print('hello')
    await asyncio.sleep(3)
    print('world')

asyncio.run(main())

Is there something inherent in how git bash treats I/O, that causes this behaviour?

I'm using Python 3.10.2 on Windows 10. Git version 2.24.1.windows.2.

  • One shell is probably line buffering and the other is block buffering. Check the buffering settings in both terminals. – Silvio Mayolo Mar 14 '22 at 01:42
  • Does the issue persist with the [latest Git For Windows](https://github.com/git-for-windows/git/releases), like Git for Windows 2.35.1.2? – VonC Mar 14 '22 at 07:57
  • Please see also: [How can I flush the output of the print function (unbuffer python output)?](https://stackoverflow.com/questions/230751/how-can-i-flush-the-output-of-the-print-function-unbuffer-python-output) – Mofi Mar 14 '22 at 16:33
  • @SilvioMayolo I haven't found a way to do this in git bash, are you sure this is possible? Or is it solely dependent on the code that writes to the terminal? See my updated answer. – Nikita Traynin Mar 17 '22 at 18:09

1 Answers1

2

Per Mofi's comment, I changed my code to this:

import asyncio

async def main():
    print('hello', flush=True)
    await asyncio.sleep(3)
    print('world', flush=True)

asyncio.run(main())

This forces the buffer to flush after both prints, sending it to the terminal. It works in Git Bash now.

Details: From what I now understand, under the hood, python sets the buffering depending on the detected device. From https://docs.python.org/2/library/functions.html#open, files are "usually line buffered for tty devices and fully buffered for other files". Print uses the default sys.stdout file object to write to.

Running a new module with the following code: import sys

print(f'{sys.stdout.isatty()=}')

It prints 'sys.stdout.isatty()=True' in cmd but 'sys.stdout.isatty()=False' in git bash, which explains why stdout chooses to fully buffer in git bash, not print until the code exits, and line buffers in cmd.