py2exe not recognizing jsonschema

747 views Asked by At

I've been attempting to build a Windows executable with py2exe for a Python program that uses the jsonschema package, but every time I try to run the executable it fails with the following error:

File "jsonschema\__init__.pyc", line 18, in <module>
File "jsonschema\validators.pyc", line 163, in <module>
File "jsonschema\_utils.pyc", line 57, in load_schema
File "pkgutil.pyc", line 591, in get_data
IOError: [Errno 0] Error: 'jsonschema\\schemas\\draft3.json'

I've tried adding json and jsonschema to the package options for py2exe in setup.py and I also tried manually copying the jsonschema directory from its location in Python27\Libs\site-packages into library.zip, but neither of those work. I also attempted to use the solution found here (http://crazedmonkey.com/blog/python/pkg_resources-with-py2exe.html) that suggests extending py2exe to be able to copy files into the zip file, but that did not seem to work either.

I'm assuming this happens because py2exe only includes Python files in the library.zip, but I was wondering if there is any way for this to work without having to convert draft3.json and draft4.json into .py files in their original location.

Thank you in advance

1

There are 1 answers

0
Anders Wiklund On

Well after some more googling (I hate ugly) I got it working without patching the build_exe.py file. The key to the whole thing was the recipe at http://crazedmonkey.com/blog/python/pkg_resources-with-py2exe.html. My collector class looks like this:

from py2exe.build_exe import py2exe as build_exe

class JsonSchemaCollector(build_exe):
   """
       This class Adds jsonschema files draft3.json and draft4.json to
       the list of compiled files so it will be included in the zipfile.
   """

    def copy_extensions(self, extensions):
        build_exe.copy_extensions(self, extensions)

        # Define the data path where the files reside.
        data_path = os.path.join(jsonschema.__path__[0], 'schemas')

        # Create the subdir where the json files are collected.
        media = os.path.join('jsonschema', 'schemas')
        full = os.path.join(self.collect_dir, media)
        self.mkpath(full)

        # Copy the json files to the collection dir. Also add the copied file
        # to the list of compiled files so it will be included in the zipfile.
        for name in os.listdir(data_path):
            file_name = os.path.join(data_path, name)
            self.copy_file(file_name, os.path.join(full, name))
            self.compiled_files.append(os.path.join(media, name))

What's left is to add it to the core setup like this:

options = {"bundle_files": 1,    # Bundle ALL files inside the EXE
           "compressed": 2,      # compress the library archive
           "optimize": 2,        # like python -OO
           "packages": packages, # Packages needed by lxml.
           "excludes": excludes, # COM stuff we don't want
           "dll_excludes": skip} # Exclude unused DLLs

distutils.core.setup(
    cmdclass={"py2exe": JsonSchemaCollector},
    options={"py2exe": options},
    zipfile=None,
    console=[prog])

Some of the code is omitted since it's not relevant in this context but I think you get the drift.