Understanding –onefile Mode
In --onefile mode, Pyinstaller bundles all the files, including the image files, into a single executable file. When the executable is run, Pyinstaller extracts the bundled files into a temporary directory and runs the application from there. This unpacking operation takes some time, so onefile mode is slower than the default directory mode.
Any datafile you include will be located inside this temporary folder. However, there is a problem that frequently occurs.
Let’s assume you have included a file called “image.png” as a datafile in your application. Somewhere in your code, you have used this image as “image.png” (e.g like in a function call). This assumes that your image is located in the same directory as your Python script.
Here’s what it may look like in Pillow.
from PIL import Image
img = Image.open("image.png")
Now this code will run perfectly fine as a python (.py) file. But when you convert it to an executable with the --add-data option, then this will most likely not work. This is because the image gets moved to a temporary folder which may have a different file path.
This issue itself is a bit complex, and varies a bit depending on the system and OS. Luckily, the solution is fairly straightforward.
Here is the code snippet that you will be needing. Simply wrap all of your file paths with this function call, and you should be good to go. Basically what this does, is acquire the base path of the temporary folder (which is located in a system variable called _MEIPASS) and then joins this with the relative path you passed in, to get the combined full path.
import sys
import os
def resource_path(relative_path):
""" Get absolute path to resource, works for dev and for PyInstaller """
base_path = getattr(sys, '_MEIPASS', os.path.dirname(os.path.abspath(__file__)))
return os.path.join(base_path, relative_path)
So after modifying your code, it should look like this.
from PIL import Image
img = Image.open(resource_path("image.png"))
```python
Your code should now work perfectly, both as a regular Python script (.py) and a Python executable (.exe).
发表回复