3

I used to add shebang line at top of Python script as,

#!/usr/bin/python
...

And I can execute the my.py file by,

chmod a+r my.py
./my.py

But after compiled to bytecode, the script can only be executed by python and the shebang does not work anymore.

python my.pyc

Is there anyway to make shebang workable to compiled python script?

./my.pyc
Takol
  • 1,620
  • 1
  • 12
  • 13
  • 2
    You're not supposed to execute `.pyc` files, why are you trying to do this? – Thomas Orozco Feb 17 '14 at 10:03
  • 1
    We have to deliver the compiled pyc but not source code for our product. – Takol Feb 19 '14 at 01:05
  • Please bear in mind that full source code (including docstrings) can be recovered easily from Python bytecode with FOSS tools. There are some DIY techniques to make decompilation a bit more difficult, but there is no real obfuscator for Python. This is not to say that you should distribute full source code, of course, but remember that reversing pyc is almost trivial. – Stefano Sanfilippo Feb 20 '14 at 10:42
  • 2
    Hi Stefano, Thanks for your reminding. With delivering .pyc it usually means "ok I know you can decompile it but be aware that I do not like you do so." – Takol Feb 24 '14 at 00:40

3 Answers3

7

Shebang works only for text scripts, not binary files. Nevertheless, you can use binfmt_misc to execute *.pyc files directly, as reported in this Python ML thread:

Linux, you can use binfmt_misc to make executables out of pyc code. Run:

import imp,sys,string
magic = string.join(["\\x%.2x" % ord(c) for c in imp.get_magic()],"") 
reg = ':pyc:M::%s::%s:' % (magic, sys.executable) 
open("/proc/sys/fs/binfmt_misc/register","wb").write(reg)

once on your Linux system (or, rather, at boot time), and all pyc files become executable (if the x bit is set).

In Debian, installing the binfmt-support package will do that for you.

(emphasis is mine, note that this will apply to all Debian derivatives, including Ubuntu. The same solution works in Fedora too).

Stefano Sanfilippo
  • 32,265
  • 7
  • 79
  • 80
  • hi Stefano. this method supports many python versions (and .pyc) on the same host, right? can I set in procfs the python interpreter and one of its options? – Massimo Nov 15 '19 at 00:13
0

No. But you can use other OS-specific mechanisms for invoking arbitrary executable files, e.g. binfmt_misc.

Ignacio Vazquez-Abrams
  • 776,304
  • 153
  • 1,341
  • 1,358
0

Here is an updated python 3 version of Stefano Sanfilippo's answer:

import imp,sys,string
magic = "".join(["\\x%.2x" % c for c in imp.get_magic()])
reg = ':pyc:M::%s::%s:' % (magic, sys.executable) 
open("/proc/sys/fs/binfmt_misc/register","w").write(reg)
  • 1
    `importlib.util.MAGIC_NUMBER` is the new replacement for `imp` according to https://docs.python.org/3/library/imp.html#imp.get_magic – Marcin Jan 01 '19 at 16:36