linux - What does the file extension do if I can execute a python file without it?
2014-07
I'm using Ubuntu 14.04. And I have an astonish finding today: I can execute a python file without a file extension!
e.g.
$ echo " print 'hello' " > z
$ python z
hello
So, why do we need a file extension? Does it has authentic influence to the file other than tell people semantically what file this is?
If you are talking about the extension, Linux does not use extensions the same way Windows does, in fact, extensions have no meaning at all in Linux and are just part of the filename. They are still being used a lot to make it easier for people to recognize files. One common occurrence where extensions are not being used is with binary executables (you can use python
instead of python.exe
).
There are two ways of running scripts:
Invoking from shell (
./scriptname.py
): In the script, the first line will say something along the lines of#!/usr/bin/python
. The#!
instructs the kernel to use the subsequent file as interpreter for the script.From http://en.wikipedia.org/wiki/Shebang_%28Unix%29
The shebang is actually a human-readable instance of a magic number in the executable file, the magic byte string being 0x23 0x21, the two-character encoding in ASCII of #!. This magic number is detected by the "exec" family of functions, which determine whether an image file is a script or an executable binary. The presence of the shebang will result in the execution of the specified executable, usually an interpreter for the script's language.
Invoking the interpreter with script as argument (
python scriptname
). If you do this, you start the interpreter, and you tell it explicitly what script to run. The script can be any file, with any 'extension'.
I noticed importing an executable Python file saves a *.py[co] file, as expected, but that file also is marked executable. Randomly, I wondered if I could execute this file directly, and it worked!
Steps to duplicate:
$ echo 'print "Worked."' > testcase.py
$ chmod u+x testcase.py
$ python -c 'import testcase'
Worked.
$ ./testcase.pyc
Worked.
How did this work? Why didn't I get an error message? Is my system, Ubuntu 9.04, doing something special, or am I forgetting something on how Linux works in general?
$ python --version
Python 2.6.2
$ hd testcase.pyc
00000000 d1 f2 0d 0a a4 4f 08 4b 63 00 00 00 00 00 00 00 |.....O.Kc.......|
00000010 00 01 00 00 00 40 00 00 00 73 09 00 00 00 64 00 |[email protected].|
00000020 00 47 48 64 01 00 53 28 02 00 00 00 73 07 00 00 |.GHd..S(....s...|
00000030 00 57 6f 72 6b 65 64 2e 4e 28 00 00 00 00 28 00 |.Worked.N(....(.|
00000040 00 00 00 28 00 00 00 00 28 00 00 00 00 73 0b 00 |...(....(....s..|
00000050 00 00 74 65 73 74 63 61 73 65 2e 70 79 74 08 00 |..testcase.pyt..|
00000060 00 00 3c 6d 6f 64 75 6c 65 3e 01 00 00 00 73 00 |..<module>....s.|
00000070 00 00 00 |...|
00000073
(Including hexdump to show there's no shebang line, and reading about .pyc format, there's nothing here that isn't highly specific to Python.)
Perhaps your system has a binfmt_misc entry for .pyc
files. Look in /proc/sys/fs/binfmt_misc
for the entry.
.pyc files are byte compiled versions of the original .py file. When a .py file is executed by python, it first checks to see if there is a .pyc file with the same name and that the original .py file hasn't been modified since the .pyc file was created. It both of these are true then it executes the .pyc file because it can save the step of byte compiling the .py file thus making the execution time faster. So the .pyc file really is executable just like you discovered.
Just because a file is marked executable does not mean that the OS knows how to execute it. What happened here is that the .pyc file inherited some of the permissions (or assumed default filesystem permissions, for example, if you're on a FAT32 drive in Linux).
In general, you don't execute .pyc files. Python stores them so it doesn't have to recompile the code every time it is imported.