Messages inside input() are not flushed before keep waiting user iteraction
Bug description
When or program relies on a python library that has something like x = input('Please, enter your info: ') the phrase 'Please enter your info: ' is not sent to the .on('message', m => {}) listener from python-shell library and the program keep stuked waiting user input, but the user don't know what should be inputed.
Python code
x = input('Please, enter your info: ')
print(x)
Javascript code
import path from 'path';
import { PythonShell } from 'python-shell';
const rootDir = path.dirname(__dirname);
export const pythonOptions: Options = {
mode: 'text',
pythonPath: '/usr/bin/python',
pythonOptions: ['-u'], // get print results in real-time
};
pythonOptions.scriptPath = path.join(rootDir, 'python', `id1234`); // currentFolder/python/id1234/start.py
const python = new PythonShell('start.py', pythonOptions);
python
.on('message', (line: string) => {
console.log(line) // this line do not print 'Please, enter your info:' **before** I input the data
})
.on('error', err => {
console.log(err);
})
.on('close', () => {
console.log('program finished')
});
setTimeout(() => {
python.send('this is my info'); // everything is printed after this sending this
}, 100000);
Expected behavior
'Please, enter your info: ' should be sent to .on('message', m => {}) listener before the program keep waiting user input. It should be printered before, as it happens when python program is runned from the terminal
Actual behavior
'Please, enter your info: ' is logged on .on('message', m => {}) only after user send his input. If he never send, it's never printed
Other Information
- OS: Ubuntu 18.04 and Ubuntu 20.04
- Python Version: 3.8
- Node Version: 14.7
Python's input function does not add a newline at the end. If you look in https://github.com/extrabacon/python-shell/blob/master/index.ts and search for "message" you would eventually find this:
let parts = (''+data).split(newline);
if (parts.length === 1) {
// an incomplete record, keep buffering
this._remaining = (this._remaining || '') + parts[0];
return this;
}
The code above buffers stdout until it receives a newline. input does not send a newline, so the message event is not immediately emitted.
You can fix this by adding a newline to the input message or moving the input message to a print().
I'm using this workaround for now (move input message to a print). The problem is when the input field is inside a library, which forces me to edit the library code. I wish we had one way to do that without editing the third part code
You can use the binary mode in pythonshell.
Can you give me more details on how this would make it work? I'm not so familiar with that. Thanks a lot!