22

I am using the input function from fileinput module to accept script via pipes or input file Here is the minimum script:

finput.py

import fileinput

with fileinput.input() as f:
    for line in f:
        print(line)

After making this script executable, I run ls | ./finput.py and get unexpected error message

./finput.py: line 1: import: command not found
./finput.py: line 3: syntax error near unexpected token `('
./finput.py: line 3: `with fileinput.input() as f:'

The only fix I found is when I add #!/usr/bin/env/python3 before the import statement.

But this issue seems to be related only to the fileinput module. Since the following script worked well without a shebang:

fruit.py

import random

fruits = ["mango", "ananas", "apple"]
print(random.choice(fruits))

Now what am I missing? Why can't the import command be found since the shebang is not required in finput.py?

ouflak
  • 2,458
  • 10
  • 44
  • 49
styvane
  • 59,869
  • 19
  • 150
  • 156

1 Answers1

63

Your need to tell your OS that this is a Python program, otherwise, it's interpreted as a shell script (where the import command cannot be found).

Like you identified, this is done by using a shebang line:

#!/usr/bin/env python3

This is only needed if you are going to run your script like this: ./script.py, which tells your OS "run this executable". Doing so requires that your OS identify how it's supposed to run the program, and it relies on the shebang line for that (among other things).

However if you run python script.py (which I'm guessing you did for fruit.py), then Python does not ask your OS whether that is a Python program or not, so the shebang line doesn't matter.

Thomas Orozco
  • 53,284
  • 11
  • 113
  • 116
  • 2
    Also please remember you will need to make the file executable – holdenweb Dec 19 '14 at 10:41
  • Passing a "python3" parameter to the env script tells env to run python3 where ever it's found in the path, right? So this avoids having to hardcode the path to the python3 executable? Could you also use #!/usr/bin/bash -c python3 ? – Ben Slade May 06 '20 at 18:57
  • 1
    @BenSlade Unfortunately many systems only support a single argument in the #! line, so giving both `-c` and `python3` wouldn't be reliable. Also, that would create a separate bash process, the script wouldn't receive any arguments on `sys.argv`, etc. – Warbo Jul 29 '21 at 18:05