7

I am trying to compile a python file with Nuitka in stead of Pyinstaller. Everything is going great except for the facts that I do not understand how I should add another data file to the python file.

The problem

If I want to add an image to my python file in Pyinstaller (in Windows) I would do:

wine /root/.wine/drive_c/Python27/pyinstaller.exe --add-data "/root/Downloads/car.jpg;." --onefile --noconsole --icon /root/Downloads/icon.ico pythonfile.py 

Now if I would open this exe file I would run the python file and open the car.jpg file.

I want to do something similar using Nuitka. When I looked at the documentation of Nuitka I saw that I probably needed to use the --include-data-file=<source>=<target> argument.

I tried this and it gave no errors, but when I open the created exe file, it does not open the given file. All the other arguments worked as I wanted, so only the --include-data-file argument does not give the wanted result

This is the Nuitka command I tried:

.\python.exe -m nuitka --mingw64 .\pythonprogram.py --standalone --onefile --windows-icon-from-ico=pdf.ico --windows-disable-console --include-data-file=C:\Users\User\AppData\Local\Programs\Python\Python39\*.pdf=mypdf.pdf

My question(s):

  • Am I using the correct argument?
  • Is this even possible with Nuitka?
  • How would I fix my problem?

Thanks in advance!

Coder
  • 159
  • 1
  • 9

2 Answers2

3

First of all, when encountering unexpected behaviour in Nuitka (in this case, you'd expect a file to open, which it didn't) I highly recommend removing the --windows-disable-console argument and observing the terminal output; without it debugging the compiled program is virtually impossible. You can also get a lot of information by analyzing Nuitka's output during transpiling and compilation (for example, there may appear a warning informing you about including numpy's plugin in order to add support for the numpy module).

Now, moving on to your questions:

  • Am I using the correct argument?

Yes, argument --include-data-file=<source>=<target> is correct if what you want is to embed one file.

What is however very important when it comes to programs compiled with --onefile argument is how the files are loaded internally, in the .py files.

I feel like the best thing I can do is show an example of my own (I'm using pygame for my project, but this way of loading files should work in any circumstance):

    import os
    import pygame
    
    
    def load_file(file_name: str) -> str:
        return os.path.join(os.path.dirname(__file__), file_name)
    
    
    image_1_sprite = pygame.image.load(load_file("textures/image_1.png"))

I would then use Nuitka as such: python -m nuitka --onefile --include-data-dir=../workingdir/textures=textures main.py or, if you want to include just one file, python -m nuitka --onefile --include-data-file=../workingdir/textures/image_1.png=textures/image_1.png main.py, where workingdir is the directory in which main.py resides (I recommend using relative paths to make the repository portable, because if someone were to download your source code and save it, for example, on the D:\ hard drive - the executed command would fail).

chubercik
  • 534
  • 1
  • 5
  • 13
1

A pathlib alternative to @chubercik's load_file (which I would call rel_to_abs_path, perhaps) would be:

def rel_to_abs_path(rel_path: str) -> Path:
   # Accepts a relative path (assumed correct) and returns an absolute path.
   return Path(rel_path).resolve()
user16217248
  • 3,119
  • 19
  • 19
  • 37
Daffodil
  • 11
  • 2