Possible approach
In Linux you can use binfmt_misc. See the documentation, it states:
First you must mount
binfmt_misc:mount binfmt_misc -t binfmt_misc /proc/sys/fs/binfmt_misc
but Debian or Ubuntu (and possibly other distros that use systemd) mount this automatically out of the box. If mount | grep binfmt_misc shows binfmt_misc mounted on /proc/sys/fs/binfmt_misc then it's already set up.
You can manually assign /usr/bin/python3 to the py"extension" by invoking:
echo ':py:E::py::/usr/bin/python3:' | sudo tee /proc/sys/fs/binfmt_misc/registerFor completeness, this is how you manually unregister:
echo -1 | sudo tee /proc/sys/fs/binfmt_misc/pyTo make the assignment survive reboots (if your Linux uses systemd-binfmt.service), create a py.conf file in /etc/binfmt.d/ with the following content:
# Run .py files with /usr/bin/python3:py:E::py::/usr/bin/python3:See man 5 binfmt.d for details.
My tests indicate the defined interpreter wins with the shebang, if any. In other words: after applying the above, a shebang in a *.py file will be irrelevant, /usr/bin/python3 will be used anyway.
Personal view
The approach works and you may even like it, I'm not a fan of it though. My reasons:
If you sometimes forget the shebang, you can forget the
py"extension" as well. Frankly, in my opinion you should forget it, because…"Extensions" for executable files are ugly. Imagine you have rewritten your
tool.pyin C or whatever; are you going to change the filename? If so, everything that usestool.pymust be updated. If the file was namedtoolfrom the beginning, then the world could start using the new release just like that, maybe even without realizing something has changed. Relying on magic bytes (like the shebang) makes this easy.