2

I just came across shebangs (#!) for the first time while learning Python and I'm still trying to understand how exactly they work. After doing some research, I landed on this page where it listed four different types of shebangs. However, I'm not really sure what the difference is in Windows.

#! /usr/bin/env python
#! /usr/bin/python
#! /usr/local/bin/python
#! python

Now, I'm betting that the first one has something to do with virtual environments, but I'm not quite sure what. And according to this StackOverflow thread, the paths listed above actually are for POSIX systems, not for Windows... which confounds me even more because they are somehow being translated into Windows directories through some magic. Here's a quote:

A bin directory is created on POSIX systems only . . . Some paths within the virtualenv are slightly different on Windows: scripts and executables on Windows go in ENV\Scripts\ instead of ENV/bin/ and libraries go in ENV\Lib\ rather than ENV/lib/.

Can anyone give a beginner a little more information on how exactly shebangs like these work on Windows?

Community
  • 1
  • 1
Taylor Liss
  • 593
  • 4
  • 27

1 Answers1

3

The documentation is not totally explicit, but on my reading of it, there is no difference between those shebang lines. The shebang handling on Windows is purely "virtual" --- that is, the paths in the shebang lines are not actually mapped onto any paths on the Windows file system. Rather, the use of any of these "virtual paths" simply means "use the default system Python when running this file via the py Python launcher". The purpose of allowing the shebang line on Windows is to let the Python script specify arguments to Python, or Python versions (e.g., python3). You can find more info about how the default system Python is determined, how to override it, etc., in the documentation linked above.

Incidentally, note that on Windows these shebangs are only used when you run the Python script using the py launcher.

BrenBarn
  • 242,874
  • 37
  • 412
  • 384
  • If I understand you right - that means that all four do exactly the same thing? – Taylor Liss Aug 18 '15 at 05:42
  • 2
    @TaylorLiss: Yes. On Unix they may do something different, but on Windows the path doesn't matter. – BrenBarn Aug 18 '15 at 05:43
  • Ah, awesome! Much simpler than I first thought. Thanks! – Taylor Liss Aug 18 '15 at 05:44
  • 1
    `/usr/bin/env python` searches `PATH` for the target python.exe, which will use an active virtual environment. – Eryk Sun Aug 18 '15 at 05:53
  • @eryksun: On Windows? I don't see anything in the docs that indicates that. – BrenBarn Aug 18 '15 at 05:55
  • Sorry, I can't find it in the docs. I learned from reading the source. [`builtin_virtual_paths`](https://hg.python.org/cpython/file/v3.4.3/PC/launcher.c#l662) defines the `search` field to `TRUE` for the env virtual path. Then on line 1217 in `maybe_handle_shebang`, if no version is specified and `search` is true, it calls [`find_on_path`](https://hg.python.org/cpython/file/v3.4.3/PC/launcher.c#l725). – Eryk Sun Aug 18 '15 at 06:15
  • See [issue 17903](http://bugs.python.org/issue17903). Apparently no one thought to update the docs when this feature was added to Python 3.4. – Eryk Sun Aug 18 '15 at 06:21
  • @eryksun: Interesting. I guess that's worth filing a bug about in itself. – BrenBarn Aug 18 '15 at 06:21