11
votes

I have the canonical shebang at the top of my python scripts.

#!/usr/bin/env python

However, I still often want to export unbuffered output to a log file when I run my scripts, so I end up calling:

$ python -u myscript.py &> myscript.out &

Can I embed the -u option in the shebang like so...

#!/usr/bin/env python -u

and only call:

$ ./myscript.py &> myscript.out &

...to still get the unbuffering? I suspect that won't work, and want to check before trying. Is there something that would accomplish this?

3
Yes, you should. The "shebang" is just a pointer to the binary application in charge of the script. If not you can create a alias alias ppython="python -u" and just use #!/usr/bin/env ppythonTorxed
Torxed, did you try your answer? That approach doesn't work in OSX or Linux. If it works in your OS, please share the details since that would be interesting. The reason it doesn't work in OSX or Linux (or I would believe, any flavor of unix) is that env searches for an executable on the path, and aliases are not on the path. Aliases don't work on the shebang line in the same way and for the same reason that built-ins don't work on the shebang line. If your OS allows this, please share!Chris Johnson

3 Answers

12
votes

You can have arguments on the shebang line, but most operating systems have a very small limit on the number of arguments. POSIX only requires that one argument be supported, and this is common, including Linux.

Since you're using the /usr/bin/env command, you're already using up that one argument with python, so you can't add another argument -u. If you want to use python -u, you'll need to hard-code the absolute path to python instead of using /usr/bin/env, e.g.

#!/usr/bin/python -u

See this related question: How to use multiple arguments with a shebang (i.e. #!)?

3
votes

A portable way to do this is to create another executable that embodies your options.

For example, put this file on your path and name it upython, and make it executable:

#!/usr/bin/env bash
python -u -and -other -options "$@"

... using whatever options you need. Then your myscript.py script can be like this:

#!/usr/bin/env upython
(... your normal Python code ...)

Torxed suggested doing this via a shell alias. I'd be very surprised if that worked in any version of unix. It doesn't work in the few distributions I just tested. My approach will work in any unix.

3
votes

In new versions of env since coreutils 8.30 there is option -S for this. Citation from man env:

   The -S option allows specifing multiple parameters in a script.  Running a script named 1.pl containing the follow‐
  ing first line:

         #!/usr/bin/env -S perl -w -T

  Will execute perl -w -T 1.pl .

  Without the '-S' parameter the script will likely fail with:

         /usr/bin/env: 'perl -w -T': No such file or directory