2

So now, I have a python program which I would like to convert into an executable(preferably a single file). Right now the target systems are only RedHat(and CentOS) and Debian(and Ubuntu).

First, I've tried the PyInstaller but after running it, it creates a .spec file and 2 folders called build and dist. I have no idea how to proceed from there.

Second, I tried the freeze.py which ships with python. I understand the usage is as follows:

python /path/to/freeze.py  /path/to/myfile.py

This throws an error ***Test Failed*** 2 failures and NameError: name 'testdata' is not defined

The full error is as follows:

**********************************************************************
File "/usr/lib/python2.6/site-packages/freeze.py", line 117, in __main__.freeze
Failed example:
    testdata = json.loads(
        gzip.open("testdata.json.gz", "r").read().decode()
    )
Exception raised:
    Traceback (most recent call last):
      File "/usr/lib64/python2.6/doctest.py", line 1253, in __run
        compileflags, 1) in test.globs
      File "<doctest __main__.freeze[3]>", line 2, in <module>
        gzip.open("testdata.json.gz", "r").read().decode()
      File "/usr/lib64/python2.6/gzip.py", line 33, in open
        return GzipFile(filename, mode, compresslevel)
      File "/usr/lib64/python2.6/gzip.py", line 79, in __init__
        fileobj = self.myfileobj = __builtin__.open(filename, mode or 'rb')
    IOError: [Errno 2] No such file or directory: 'testdata.json.gz'
**********************************************************************
File "/usr/lib/python2.6/site-packages/freeze.py", line 121, in __main__.freeze
Failed example:
    freeze(testdata) == freeze_fast(testdata)
Exception raised:
    Traceback (most recent call last):
      File "/usr/lib64/python2.6/doctest.py", line 1253, in __run
        compileflags, 1) in test.globs
      File "<doctest __main__.freeze[4]>", line 1, in <module>
        freeze(testdata) == freeze_fast(testdata)
    NameError: name 'testdata' is not defined
**********************************************************************
1 items had failures:
   2 of   8 in __main__.freeze
***Test Failed*** 2 failures.

I'd like some help to using either of the 2 (or any other tool which will help me achieve the same result).

Thanks.

rahuL
  • 3,330
  • 11
  • 54
  • 79
  • Also, With your PyInstaller, try going into the 'dist' folder, or maybe the 'build' folder. Judging from your description I am pretty sure it worked, we just can't find the executables, and I will bet they are in the 'dist' folder. – charmoniumQ Aug 09 '13 at 08:44
  • @Sam: The PyInstaller created a folder called myfile Inside it were 2 folders called build and dist and a third file called spec. Under build, it has some files with extensions .toc,.pkg and .pyz. Under the dist folder, it has files with extensions .so - thing is I don't know where to go from there. – rahuL Aug 09 '13 at 08:50

4 Answers4

2

If you want to make it executable, you have to chmod +x /path/to/script.py. This gives anybody permission to run the file. Then you can python /path/to/script.py.

You still need to start the command with python, that is ugly. If you add this line #!/usr/bin/env python to the first line of your script. This is callled a shebang or a hashbang. Then (still remember to chmod it) you can /path/to/script.py and it will execute.

If you are already in the directory of your script you can ./script.py. (still remember to chmod it and at a shebang)

If you still aren't satisfied, and you want to type in just the name of your script, you move the script into one of the folders on your path (which you can find by typing echo $PATH in shell, typically this is /usr/, /bin/, /usr/local/bin, or something like that). If you move your script into one of those folders, then you can just script.py. If you do this, I recommend you drop the .py extension, so you can just type in script. This will kind of make look like other unix shell commands (ls, grep, cat) at least in its invocation.

charmoniumQ
  • 5,214
  • 5
  • 33
  • 51
  • Sorry, I got the terminology wrong. Edited the question. I was going by what I googled – rahuL Aug 09 '13 at 08:32
  • And after I convert it to byte code, what would the next step be? – rahuL Aug 09 '13 at 08:35
  • Well, actually freeze.py IS intended to turn python scripts into stand-alone executables. It doesn't always work well, though. – Alex Aug 09 '13 at 08:38
  • Sorry if this sounds confusing Sam. The intention is to create a single executable file which the user can simply install (from the command prompt) but should not be able to see the source of the python code. This is the first time I am trying something like this so maybe the terms I use/used to ask this question are wrong – rahuL Aug 09 '13 at 08:55
  • Sorry stack overflow was down for a while. If you are trying to hide your source code, I don't think you will be able to find an effective solution. 4 other SO threads have discouraged this practice: [first post](http://stackoverflow.com/questions/261638/how-do-i-protect-python-code), [second post](http://stackoverflow.com/questions/4599166/python-compiling-script-safely), [third post](http://stackoverflow.com/questions/3344115/obfuscating-python-code), [fourth post](http://stackoverflow.com/questions/576963/python-code-obfuscation) – charmoniumQ Aug 09 '13 at 09:24
  • Thanks a lot, Sam. Based on your answers and comments, I had a look at the whole thing again and read the docs for PyInstaller. Managed to find the `-F` option while compiles it into a single file. Thanks again for cluing me in. Cheers!! – rahuL Aug 09 '13 at 10:40
  • Oh and for "hiding the code" - I myself am against it. Unfortunately, we sometimes find ourselves in a position where we're "asked" to do it. – rahuL Aug 09 '13 at 10:48
2

You might wish to investigate Nuitka. It takes python source code and converts it in to C++ API calls. Then it compiles into an executable binary (ELF on Linux). It has been around for a few years now and supports a wide range of Python versions.

You will probably also get a performance improvement if you use it. Recommended.

cdarke
  • 42,728
  • 8
  • 80
  • 84
2

Using the -F flag to pyinstaller.py will create a single, executable file and drop it into the dist/ directory.

pyinstaller.py --help shows a long list of options.

The pyinstaller-X.X/doc directory has the full manual in HTML and PDF.

zsxwing
  • 20,270
  • 4
  • 37
  • 59
8g7YmDoy
  • 21
  • 1
-1

You can try using cython to turn it into a c executable

Alex
  • 18,332
  • 10
  • 49
  • 53