2

How exactly does Python receive

echo input | python script

and

python script input

differently? I know that one comes through stdin and the other is passed as an argument, but what happens differently in the back-end?

4
  • Does python script input really work if you didn't use sys.argv[1] as the input? Commented Jan 14, 2016 at 5:29
  • Okay so let's test. The content of script is print(input()). Does echo 'foobar' | python script just print the output, instead of ask you for the input? And, does python script 'foobar' also print the foobar, and didn't run the input()? Also try print(__import__('sys').argv[1]), and check what the output is. Commented Jan 14, 2016 at 5:41
  • Weird results. For the first one, it returns an error immediately, and for the second one, it runs the input, then throws an error. For the last one, I think you meant .argv[0]? Commented Jan 14, 2016 at 5:44
  • Never mind its argv[1] Commented Jan 14, 2016 at 6:33

1 Answer 1

8

I'm not exactly sure what is confusing you here. stdin and command line arguments are treated as two different things.

Since you're most likely using CPython (the C implementation of Python) the command line args are passed automatically in the argv parameter as with any other c program. The main function for CPython (located in python.c) receives them:

int main(int argc, char **argv)  // **argv <-- Your command line args
{
    wchar_t **argv_copy;   
    /* We need a second copy, as Python might modify the first one. */
    wchar_t **argv_copy2;
    /* ..rest of main omitted.. */

While the contents of the pipe are stored in stdin which you can tap into via sys.stdin.

Using a sample test.py script:

import sys

print("Argv params:\n ", sys.argv)
if not sys.stdin.isatty():
    print("Stdin: \n", sys.stdin.readlines())

Running this with no piping performed yields:

(Python3)jim@jim: python test.py "hello world"
Argv params:
  ['test.py', 'hello world']

While, using echo "Stdin up in here" | python test.py "hello world", we'll get:

(Python3)jim@jim: echo "Stdin up in here" | python test.py "hello world"
Argv params:
 ['test.py', 'hello world']
Stdin: 
 ['Stdin up in here\n']

Not strictly related, but an interesting note:

Additionally, I remembered that you can execute content that is stored in stdin by using the - argument for Python:

(Python3)jimm@jim: echo "print('<stdin> input')" | python -
<stdin> input

Kewl!

Sign up to request clarification or add additional context in comments.

4 Comments

I'm sorry, but what is python.c?
The main function for CPython, remember, python is written in the c language.
Ok I just didn't know that stdin and cmd arguments were treated completely differently, thanks!
Thanks for the answer, Jim. Though other answers note that stdin and argv are not equivalent, yours is the first I've found that actually explains why that's the case.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.