Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to remove output buffering when running Python in Sublime Text 3

How can I remove the output buffering from Sublime Text 3 when I build a Python 3 script? I would like real-time output.

I am using Sublime Text 3 with the Anaconda plugin, Python 3.6 and Linux Mint 18. When I run a simple script using control-b:

print('hello')

I get an instant output in a separate window called 'Build output'. When I use a script with a repeated output, such as:

from time import sleep

count = 0
print('starting')
while True:
    print('{} hello'.format(count))
    count += 1
    sleep(0.5)

Initially I get a blank screen in 'Build output'. Some time later it populates with several hundred lines of output. It looks like the output is being buffered. When the buffer is full, it outputs all at once to the 'Build output' screen.

Edit Sublime Text allows custom build configurations. The default Python build is for python 2. I entered a build configuration for Python 3 and missed the -u flag. The fix is to put the -u flag in the Python 3 build.

File: Python3.sublime-build

{
    "shell_cmd": "/usr/bin/env python3 -u ${file}",
    "selector": "source.python",
    "file_regex": "^(...*?):([0-9]*):?([0-9]*)",
    "working_dir": "${file_path}",
}

Save in sublime_install/Data/Packages/User/Python3.sublime-build

like image 340
Oppy Avatar asked Oct 29 '22 12:10

Oppy


1 Answers

By default the exec command is used to execute the commands in build systems, and the exec command doesn't buffer output at all. There is more information in this answer (which also provides a version of exec that does line buffering) but in short exec launches one thread to handle stdout and one to handle stderr, and both forward whatever data they get to the panel as soon as they get it.

As such, a problem like the one you're describing here is generally caused by the program doing it's own buffering. Depending on the language and platform that you're using, buffering may change from what you expect in unexpected ways:

For example, see this text in the man page for stdout under Linux:

The stream stderr is unbuffered. The stream stdout is line-buffered when it points to a terminal. Partial lines will not appear until fflush(3) or exit(3) is called, or a newline is printed. This can produce unexpected results, especially with debugging output.

In the general case, the solution to this problem would be to modify the program itself to ensure that it's not buffering, and how you would do that depends on the language you're using and the platform that you're on. It could be something as simple as setting an environment variable or as complex as startup code that ensures that regardless of circumstance buffering is set as you expect it to be.

In the specific case of Python, the -u command line argument to the interpreter tells Python to keep things unbuffered:

-u     : unbuffered binary stdout and stderr; also PYTHONUNBUFFERED=x
         see man page for details on internal buffering relating to '-u'

The Python.sublime-build that ships with Sublime uses this argument to the python command to ensure that the output is unbuffered, and using that build system works as expected for your sample program.

I don't use the Anaconda package so I'm not sure if it provides it's own build systems or not, but you may want to check the build command that you're using to ensure that it uses -u.

like image 113
OdatNurd Avatar answered Nov 14 '22 13:11

OdatNurd