Is it possible to distribute only the bytecode version (.pyc file) of a Python script instead of the original .py file? My app embeds the Python interpreter and calls PyImport_Import to load a script. How can I tell it to look for a .pyc file and import that?
This should not be a problem, if you create a stand alone program using py2exe you only get the .pyc files.
Normally you don't need to tell python to look for .pyc files, it does so anyway. Only if there is a newer .py source file this is used.
However, the level of protection of you source code may not be very high.
I did it by creating .py library and simple .py program that uses that library. Then I compiled library to .pyc and distributed: program as .py source and library as compiled .pyc.
use the freeze tool, which is included in the Python source tree as Tools/freeze. It converts Python byte code to C arrays; a C compiler you can embed all your modules into a new program, which is then linked with the standard Python modules.
Note that freeze requires a C compiler
Other utilities:
1- PyInstaller
2- Py2Exe
3- Squeeze
4- cx_freeze
In the interactive interpreter, that's automatic - if there is no .py, the .pyc will still be used:
$ echo 'print "hello"' > test.py
$ python -m compileall .
$ rm test.py
$ python -m test
hello
$
Could you just try if that works the same way with the API?
Edited to add: I agree with Ber in that your code protection will be rather weak. -O will remove docstrings, if that doesn't change the behaviour of your programme, that may make reconstructing behaviour harder, but what you'd really need some sort of bytecode obfuscation.
I don't know if a ready-made obfuscation tool exists for python, but this sounds viable, if you want to / can invest the time (and don't feel all too silly doing it, and can ship your own interpreter).
Since you are writing your main program in C++, you can do whatever you want to protect your Python files. You could encrypt them for distribution, then decrypt them just in time to import them into the Python interpreter, for example.
Since you are using PyImport_Import, you can write your own __import__
hook to import the modules not from a file but from a memory buffer, so your transformation to .pyc file can happen all in memory, with no understandable Python code on disk at all.