--add-data behavior?

955 views
Skip to first unread message

Ed May

unread,
Oct 4, 2023, 3:40:37 AM10/4/23
to PyInstaller
Hi, I am having trouble and I wonder if someone can see where I am going wrong? I had a configuration that worked well previously, but since upgrading to v6 I am getting behavior I do not quite understand?

Scenario:
A simple GUI (PyQt6) app, which has an associated 'data' folder. In the data folder are some 'options' .json files that are loaded by the app at runtime. This all compiled properly to a single file previously when using PyInstaller v4/5
Screen Shot 2023-10-02 at 3.29.10 PM.png

Now when I try and build the app using just a the basic 'pyinstaller phpp_io.py', as expected this 'data' folder is not included, and so the app does not start with the required options available.

So if I instead use the commend:
pyinstaller --add-data "data:." phpp_io.py

it does build properly, but the 'data' folder is still not included anywhere that I can see? Either up at the root, or in the '_internal' folder?
Screen Shot 2023-10-02 at 3.33.13 PM.png

So if I instead try and use:
pyinstaller --add-data "data:data" phpp_io.py

then in that case then 'data' folder *does* get included, but it is now inside the '_internal' folder?
Screen Shot 2023-10-02 at 3.36.23 PM.png

So the question is: how can I properly add this 'data' folder, but not within the '_internal' folder? The app is looking for this data at the root, not within this '_internal' folder?

In my older versions of the app I don't remember ever seeing this '_internal' folder or having this occur before?

I wonder what the right method would be for a case like this?

Thank you very much for any assistance or advice on the proper configuration.

- Ed

Chris Barker

unread,
Oct 5, 2023, 4:41:39 AM10/5/23
to pyins...@googlegroups.com
How does the code find the data file? Any difference from how it does it when run on its own vs bundled?

I think you've got a bit of an issue because (I think) you're loading the file directly from the top-level script [*], and expecting the data dir to be relative to that -- but that's not very well defined in Python.

"Best practice" would be to put your data file in with the code, and read it from a location outside the top-level script. Then use the __file__ attribute in the code file reading the data to find it.

And I think PyInstaller would then "do the right thing" out of the box.

-CHB

[*] In fact, most folks recommend that top-level scripts to pretty much nothing themselves, and be pretty much as simple as:

import my_lib_front_end
my_lib_front_end.main()

This is then compatible with what, e.g. setuptools does when making console script "entry points".










--
You received this message because you are subscribed to the Google Groups "PyInstaller" group.
To unsubscribe from this group and stop receiving emails from it, send an email to pyinstaller...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/pyinstaller/492b21e0-c627-43c1-8fa8-3fa43521aa00n%40googlegroups.com.


--

Christopher Barker, Ph.D.
Oceanographer

Emergency Response Division
NOAA/NOS/OR&R            (206) 526-6959   voice
7600 Sand Point Way NE   (206) 526-6329   fax
Seattle, WA  98115       (206) 526-6317   main reception

Chris....@noaa.gov

Ed May

unread,
Oct 5, 2023, 10:00:56 AM10/5/23
to PyInstaller
Hi Chris,

Thank you very much for the advice. Currently the main App tries to find and load the support .json file at load using this function:
Screenshot 2023-10-05 at 7.36.14 AM.png
which I had thought was the recommended method for finding files? I honestly don't remember where I copy/pasted that function from - but I thought it was from the PyInstaller documentation? 

For the particular data file causing me trouble at the moment, the file gets loading by my App using that application path as the root, then a 'data' folder and the filename. I define that as a normal class-attribute in the App class:
Screenshot 2023-10-05 at 7.38.25 AM.png

and then using the path to load the file at run. This works as expected when run 'as a script' and also works ok when bundled, if I manually put the 'data/co2e_region_factors.json' file in the bundle. But for some reason I can't seem to make it bundle the file automatically anymore like it did when I was using version <6.0 ?

thanks for any thoughts or advice
best,
-Ed

bwoodsend

unread,
Oct 5, 2023, 11:13:01 AM10/5/23
to PyInstaller

Ughh, I’ve seen that snippet of misinformation before on stackoverflow. The code in the else block is what you should be running unconditionally. If that can’t find your resources then you’re putting your data files in the wrong place inside your application and you should adjust the DEST part of your --add-data flags until it does work. There is also a sys._MEIPASS variable that also gives you the application’s path but again, I try to steer people away from that because 99% of the time they’d be better off using __file__.

That code snippet works in PyInstaller <6 (well no, it breaks under onefile mode, but under onedir mode it worked) because os.path.dirname(sys.executable) used to, by happenstance rather than design, equal sys._MEIPASS. PyInstaller 6.0 moved most of the application into this new _internal directory though so now those two are no longer equal.

Chris Barker

unread,
Oct 6, 2023, 6:21:42 AM10/6/23
to pyins...@googlegroups.com
On Thu, Oct 5, 2023 at 8:13 AM bwoodsend <bwoo...@gmail.com> wrote:

Ughh, I’ve seen that snippet of misinformation before on stackoverflow.

To be fair, "putting data files next to the executable" is a long-standing tradition on Windows from way, way back -- though I don't think it's been best practice for a very long time :-(

My guideline is that there should ideally never be the need to check the frozen attribute :-)

-CHB
Reply all
Reply to author
Forward
0 new messages