binfmt support for Python scripts
binfmt-misc is a way to “exec” non-native files using an interpreter. For example you can “exec” Windows .exe files using Wine or Linux binaries for another architecture using Qemu (by the way this is not widely known, but very useful – try mounting your Raspberry Pi into /mnt/foo and then “cp /usr/bin/qemu-arm-static /mnt/foo/usr/bin/; chroot /mnt/foo” - tadaa, you are now running your RPi system on your x86 desktop!)
Anyway, I'm lazy to type “#!/usr/bin/env python3” on the beginning of each single-use Python script, and lazy to execute it using “py3 script.py” instead of just “./script.py”. I usually end up launching the “import” command from ImageMagick (sputtering weird screenshots across the filesystem) and then a bunch of shell errors.
So I just map all .py files to the python3 interpreter.
echo ":python3:E::py::/usr/bin/python3:" | sudo tee /proc/sys/fs/binfmt_misc/register
Btw. what's the difference between “#!/usr/bin/env python3” and “#!/usr/bin/python3”? There is one, besides the obvious one that weird systems may have Python installed in /opt and hardcoded path will thus not work: the kernel does not split argv for a hashbang command, so you can't pass multiple options! Try creating and running this:
/tmp> cat ./test.sh #!/bin/bash -x -v true /tmp> ./test.sh /bin/bash: - : invalid option
Fortunately, env will split it for you, at least when using -S:
> cat ./test.sh #!/usr/bin/env -S bash -x -v true > ./test.sh #!/usr/bin/env -S bash -x -v true + true
Note that this feature has been ported from BSD into GNU Coreutils only recently (2018), so it will not work on older systems.