Adding non python files to executable

380 views
Skip to first unread message

csshanka...@gmail.com

unread,
Jun 9, 2020, 4:43:00 PM6/9/20
to pyoxidizer-users
Hello,

I have a file named version.txt at the root folder of my python app. I need to include this in one file executable. I am not sure how do I do. that. The following link mentions additional files in the title, but the example shown here is for the inclusion of another python module. It would be great if someone can provide me some samples to include version.txt, .j2, .conf ....

Thanks
Sankar

Gregory Szorc

unread,
Jun 11, 2020, 9:33:03 PM6/11/20
to csshanka...@gmail.com, pyoxidizer-users
Sankar,

Assuming you are using a `setup.py` file for your Python application, you can use the `package_data` argument in your `setup.py` for registering additional files as resource files in your Python package/application. See https://packaging.python.org/guides/distributing-packages-using-setuptools/#package-data. If you do this and use a pyoxidizer.bzl method like https://pyoxidizer.readthedocs.io/en/v0.7.0/config_api.html#pythondistribution-setup-py-install to process the setup.py file, PyOxidizer should detect the resources and make them available via the `importlib.resources` and other APIs as described by https://pyoxidizer.readthedocs.io/en/latest/oxidized_importer_resource_files.html.

If you are using a pyoxidizer.bzl method to scan just the filesystem for Python files, it will fail to pick up files in the root directory because resources need to be associated with a Python package. And since Python packages are defined by a sub-directory with a __init__.py file, extra files in the root directory won't be detected as resources. The `setup.py` file feature linked earlier allows you to map files in arbitrary locations to Python packages, satisfying the requirements of PyOxidizer/Python that resource files be associated with packages.

There is a slight chance I'm wrong about there being a requirement that resource files be associated with packages [in subdirectories]. Python's documentation here isn't clear. If you can coerce Python's `importlib.resources` API to load files in the root directory of a path on `sys.path`, you will have proved my interpretation wrong and PyOxidizer's behavior should probably be changed to conform with Python's.

--
You received this message because you are subscribed to the Google Groups "pyoxidizer-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to pyoxidizer-use...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/pyoxidizer-users/94da63a5-0cc4-49ac-a833-22ab4a752015o%40googlegroups.com.

Sankaravadivel Sivarajan

unread,
Jun 13, 2020, 1:33:54 PM6/13/20
to Gregory Szorc, pyoxidizer-users
Hi Gregory,

Thanks for your response. I did not try the setup.py approach. I will give it a try.

I did make some progress with my problem. I moved version.txt into the top-level package and used importlib.resources to refer to my version.txt and as you mentioned importlib.resources expect files to be inside a package

I also got FileManifest approach work for cases where the files cannot reside inside the package folder. Here is my make_exe function

def make_install(exe):
    # Create an object that represents our installed application file layout.
    files = FileManifest()
    scripts = glob(["/home/testuser/workspace/terraform-mae/scripts/tfe.sh"], strip_prefix="/home/testuser/workspace/terraform-mae/")
    templates = glob(["/home/testuser/workspace/terraform-mae/terraform_mae/templates/**/*"], strip_prefix="/home/testuser/workspace/terraform-mae/terraform_mae/")
   
    # Add the generated executable to our install layout in the root directory.
    files.add_python_resource(".", exe)
    files.add_manifest(scripts)
    files.add_manifest(templates))

    return files

Pyoxidizer creates these directories relative to the directory where the executable exists. I added the path of the executable to sys.paths like below.

 def make_exe(dist):
    # This variable defines the configuration of the
    # embedded Python interpreter.
    python_config = PythonInterpreterConfig(
          sys_paths=["$ORIGIN","$ORIGIN/lib"],
          run_module="terraform_mae.mae"
    )
And finally, I updated my python code like below to reference those files. Not sure if this is the cleanest approach, but for works for now.
scripts = os.path.join(sys.path[0], "scripts/tfe.sh")

The bad part with the FileManifest approach is I cannot provide a single executable to my customer, instead, I need to provide a zip file with all its dependencies.

Thanks
Sankar
Reply all
Reply to author
Forward
0 new messages