1

I am attempting to include a python module (zipcodes) into a program that i am converting to an EXE. First attempt - the bz2 file that contains that data for the module did not load - so I changed the command line to pull that data in.

the test program is as simple as (ziptest.py) code below:

import zipcodes
print('Test message')
checkzip=zipcodes.matching('92688')
print(checkzip)
print("returned the right record:", checkzip[0]['zip_code']=='92688')

the pyinstaller install command is:

pyinstaller --debug all --onefile ziptest.py --add-data "venv\lib\site-packages\zipcodes\zips.json.bz2;zipcodes\zips.json.bz2"

when I run the program and capture STDERR - the lines of code that i think are most relevant are:

import 'json.encoder' # <_frozen_importlib_external.SourcelessFileLoader object at 0x0000019824E121C8>
import 'json' # <_frozen_importlib_external.SourcelessFileLoader object at 0x0000019824E018C8>
Traceback (most recent call last):
  File "ziptest.py", line 1, in <module>
  File "<frozen importlib._bootstrap>", line 983, in _find_and_load
  File "<frozen importlib._bootstrap>", line 967, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 677, in _load_unlocked
  File "<frozen importlib._bootstrap_external>", line 728, in exec_module
  File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed
  File "c:\users\ken\onedrive - rootdir\code\companyppi-scripts\temp_dir\validation\venv\lib\site-packages\zipcodes\__init__.py", line 32, in <module>
    with bz2_open(_zips_json, "rb") as f:
  File "C:\Users\ken\AppData\Local\Programs\Python\Python37\lib\bz2.py", line 318, in open
    binary_file = BZ2File(filename, bz_mode, compresslevel=compresslevel)
  File "C:\Users\ken\AppData\Local\Programs\Python\Python37\lib\bz2.py", line 92, in __init__
    self._fp = _builtin_open(filename, mode)
PermissionError: [Errno 13] Permission denied: 'C:\\Users\\ken\\AppData\\Local\\Temp\\_MEI65962\\zipcodes\\zips.json.bz2'
[10396] LOADER: Cleaning up Python interpreter.
# cleanup[3] wiping _codecs

I might need to write a hook for this module based on what I have seen so far researching, but before I dig into doing this I want to make sure this is the right path. I have to believe there are other modules that pull in source data from the module install - so I want to make my approach is proper for resolution.

K Venner
  • 11
  • 2

1 Answers1

0

My colleague helped me figure this out - first on Linux and then I got a working version on Windows.

This article gives pointers to what the problem and how to resolve it:
Adding a data file in Pyinstaller using the onefile option

Given the first answer - i modified the init.py file to be "PyInstaller" aware by adding this function to the code and replacing this line at line 31:

def resource_path(relative_path):
    """ Get absolute path to resource, works for dev and for PyInstaller """
    try:
        # PyInstaller creates a temp folder nad stores path in _MEIPASS
        base_path = sys._MEIPASS
    except Exception:
        base_path = os.path.abspath(".")

    return os.path.join(base_path, relative_path)
    
_zips_json = resource_path(os.path.join(os.path.dirname(os.path.abspath(__file__)), "zips.json.bz2"))

And I updated the EXE generation command line to look like this:

pyinstaller --onefile ziptest.py  --add-data ".\venv\Lib\site-packages\zipcodes\zips.json.bz2;zipcodes"

This creates the onefile EXE that i was hoping to create.

I have also gone over to the zipcodes project and posted this patch in hopes they will incorporate it to make their code PyInstaller compatible.

K Venner
  • 11
  • 2