Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I run Python source from stdin that itself reads from stdin?

Tags:

python

I have a Python source file that looks like this:

import sys
x = sys.stdin.read()
print(x)

I want to invoke this source file by passing it to Python's stdin:

python < source.py

After source.py is read, I want the Python program to start reading from stdin (as shown above). Is this even possible? It appears that the interpreter won't process source.py until it gets an EOF, but if an EOF is received, then sys.stdin.read() won't work.

like image 388
Matt Fichman Avatar asked Oct 15 '13 13:10

Matt Fichman


People also ask

How do you get user input from stdin in Python?

Read Input From stdin in Python using input() The input() can be used to take input from the user while executing the program and also in the middle of the execution.

Which method allows us to read data from the standard input stdin?

The readAll() method reads all remaining input on standard input and returns it as a string. As an example, the following code fragment reads all of the remaining tokens from standard input and returns them as an array of strings. String[] words = StdIn. readAllStrings();

What is SYS stdin read ()?

It will read the source file line by line. It is widely used in Online Judge System. For example: suppose we have only one number 2 will be used in the file. import sys if __name__ == "__main__": n = int(sys.stdin.readline().strip()) Read the file line by line means read the number 2 (only one line in this case).


2 Answers

Use another FD.

import os

with os.fdopen(3, 'r') as fp:
  for line in fp:
    print line,

...

$ python < source.py 3< input.txt
like image 116
Ignacio Vazquez-Abrams Avatar answered Sep 28 '22 01:09

Ignacio Vazquez-Abrams


If you don't want to do any fancy stuff on the command line beyond your example, you will have to redirect stdin to your terminal first thing in your python script. You can do that by invoking the command tty from within Python and getting the path to your tty, then changing sys.stdin to that.

import sys, os
tty_path = os.popen('tty', 'r').read().strip() # Read output of "tty" command
sys.stdin = open(tty_path, 'r') # Open the terminal for reading and set stdin to it

I believe that should do what you want.

EDIT:

I was mistaken. This will fail for your use case. You need some way of passing the current TTY path to the script. Try this instead:

import sys, os
tty_path = os.environ['TTY']
sys.stdin = open(tty_path, 'r') # Open the terminal for reading and set stdin to it

But you must then invoke the script slightly differently:

TTY=`tty` python < source.py

I should add that I think the sanest way—avoiding this issue entirely—would be to not redirect the script to python's stdin at all and just invoke it with python source.py.

like image 39
user108471 Avatar answered Sep 28 '22 00:09

user108471