PyPy doesn't find a module made of only *.pyc files

971 views Asked by At

As per my client's request I need to distribute a closed source python program with just the *.pyc files, and must be run via pypy.

The program has a subdirectory where various modules are imported:

start.pyc
backends/
   server.pyc
   ...

the first line of start.py imports backends.server, and it works when running in standard "python" mode. But if I strip all the *.py files, and try to run

(pypy)home@user:~ python start.pyc

Traceback (most recent call last):
  File "./start.py", line 4, in <module>
ImportError: No module named backends.server

I get an error saying no module named 'backends' is found, even if the 'backends' subdir is there, and the server.pyc file is there.

I remember there was a switch for pypy for exactly this behavior, but I can't seem to find it anymore. Any help?

PS this is the pypy/python version we use on an embedded ARM system.

Python 2.7.10 (c95650101a99, Sep 06 2016, 11:02:19)
[PyPy 5.4.1 with GCC 4.7.2 20120731 (prerelease)]
1

There are 1 answers

4
Armin Rigo On

Here is the way to enable loading lone .pyc files (mostly untested but should work). You need to translate pypy from sources with:

cd pypy/goal
./rpython -Ojit targetpypystandalone.py --objspace-lonepycfiles

If obfuscation is the goal, then you can also write your own import hook and load the modules from your own custom file format (then it works in a standard PyPy).

Finally, I'm not sure but I think that .pyc files are still found and loaded from .zip files. So if you package your application's .pyc files into a .zip and make the .zip available for the normal importing mechanism (I think it means adding the path to the .zip file itself into sys.path), then it should work in a standard PyPy too.

Usual comments about the ease of reverse-engineering .pyc files back to .py files apply.