0
  • My program needs to receive keyboard input.
  • It needs to print output to the terminal.
  • It needs to also dump the same output to file.

Here is the program:

> cat test.py
print(input("A man walks into a: "))

> /usr/bin/python3 test.py
A man walks into a: bar
bar

As per How to redirect output to a file and stdout, I try the following:

> /usr/bin/python3 test.py | tee foo.log
A man walks into a: bar

^C

> cat foo.log 
A man walks into a: 

Note that I hit ENTER twice then did ^c to exit, as it won't exit otherwise (it just hangs).

I can reduce the test case as follows:

/usr/bin/python -c 'print(input("A man walks into a: "))' | tee foo.log

I've also tried doing:

x = input()
with open('quux.log', 'w') as f:
    f.write(x)

... which won't create 'quux.log'

What could be going wrong? And is there a more robust approach?

Here's my system information:

> ll /usr/bin/python3
-rwxr-xr-x  1 root  wheel   134K  1 Jan  2020 /usr/bin/python3*

> /usr/bin/python3 --version
Python 3.8.2

> uname -a
Darwin pPro18.local 20.4.0 Darwin Kernel Version 20.4.0: Fri Mar  5 01:14:14 PST 2021; root:xnu-7195.101.1~3/RELEASE_X86_64 x86_64

> printenv
TERM_PROGRAM=Apple_Terminal
ANDROID_HOME=/Users/pi/Library/Android/sdk
SHELL=/bin/bash
TERM=xterm-256color
CLICOLOR=1
HISTSIZE=50000
TMPDIR=/var/folders/nj/rqdlt_hs4k5dwr5xrpgmn0kh0000gn/T/
TERM_PROGRAM_VERSION=440
OLDPWD=/Users/pi
TERM_SESSION_ID=864894DE-2B70-4E62-8ACB-E34D311CAE9D
HISTFILESIZE=50000
USER=pi
SSH_AUTH_SOCK=/private/tmp/com.apple.launchd.QiPWN8s7AJ/Listeners
LSCOLORS=GxFxCxDxBxegedabagaced
PATH=.:/usr/local/anaconda3/bin:/Users/pi/.cargo/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/Library/Apple/usr/bin:/Users/pi/bin:/Users/pi/Library/Android/sdk:/Users/pi/Library/Android/sdk/platform-tools:/Users/pi/.cargo/bin:/Users/pi/Documents/go/bin:/usr/local/Cellar/go/1.14.1/libexec/bin
__CFBundleIdentifier=com.apple.Terminal
PWD=/Users/pi
LANG=en_GB.UTF-8
XPC_FLAGS=0x0
HISTCONTROL=ignoredups:erasedups:ignorespace
XPC_SERVICE_NAME=0
SHLVL=1
HOME=/Users/pi
GOROOT=/usr/local/Cellar/go/1.14.1/libexec
LOGNAME=pi
GOPATH=/Users/pi/Documents/go
PROMPT_COMMAND=update_terminal_cwd
history -a; history -c; history -r
NDK_ROOT=/Users/pi/Library/Android/sdk/ndk-bundle
_=/usr/bin/printenv
P i
  • 29,020
  • 36
  • 159
  • 267
  • The file is simply not created. So that `input` line never completes. – P i May 28 '21 at 01:45
  • Why are you using ^c? Your script exits normally after printing the input string, with `A man walks into a: bar` in the log file. – Shawn May 28 '21 at 01:54
  • work fine for me ... maybe try `bash -c "/usr/bin/python -c 'print(input(\"A man walks into a: \"))' | tee foo.log"`.. For second part do you have space on the partition your are write and/or write permission on the folder ? – Dr Claw May 28 '21 at 01:56
  • Are you running this in some sort of environment where standard input isn't a terminal? (Or with strange terminal settings where it's not sending individual lines on to the running program but is using a bigger block buffer?) – Shawn May 28 '21 at 02:00
  • @Pi : I can't recreate your case. BTW, using `cat` is a bit unreliable for debugging this. I suggest that you use `xxd` instead for looking at the file afterwards. – user1934428 May 28 '21 at 06:38
  • @Pi : BTW: I tested your case with the command `python3 -c 'print(input("A man walks into a: "))' | tee tmp/pout.txt; xxd tmp/pout.txt` – user1934428 May 28 '21 at 06:42
  • @Pi : You seem to have used Control-C. Of course this ruins your example. Don't do this! – user1934428 May 28 '21 at 06:44

1 Answers1

1

Using sys from the standard library, you can flush the stdout buffer and ensure that a proper exit signal is emitted, which is then passed on to tee.

test.py

#!/usr/bin/env python3

import sys

print(input("A man walks into a: "))
sys.stdout.flush()
sys.exit(0)

Now tee should be able to capture all of the output correctly:

$ python test.py | foo.log
A man walks into a: bar
bar

$ cat foo.log
A man walks into a: bar
damon
  • 14,485
  • 14
  • 56
  • 75