pyoxidizer 0.24.0

Package self-contained Python applications
Documentation
.. py:currentmodule:: starlark_pyoxidizer

.. _packaging_python_executable:

===================================================
Building an Executable that Behaves Like ``python``
===================================================

It is possible to use PyOxidizer to build an executable that would
behave like a typical ``python`` executable would.

To start, initialize a new config file::

   $ pyoxidizer init-config-file python

Then, we'll want to modify the ``pyoxidizer.bzl`` configuration
file to look something like the following:

.. code-block:: python

    def make_exe(dist):
        dist = default_python_distribution()

        policy = dist.make_python_packaging_policy()
        policy.extension_module_filter = "all"
        policy.include_distribution_resources = True

        # Add resources to the filesystem, next to the built executable.
        # You can add resources to memory too. But this makes the install
        # layout somewhat consistent with what Python expects.
        policy.resources_location = "filesystem-relative:lib"

        python_config = dist.make_python_interpreter_config()

        # This is the all-important line to make the embedded Python interpreter
        # behave like `python`.
        python_config.config_profile = "python"

        # Enable the stdlib path-based importer.
        python_config.filesystem_importer = True

        # You could also disable the Rust importer if you really want your
        # executable to behave like `python`.
        # python_config.oxidized_importer = False

        exe = dist.to_python_executable(
            name="python3",
            packaging_policy = policy,
            config = python_config,
        )

        return exe

    def make_embedded_resources(exe):
        return exe.to_embedded_resources()

    def make_install(exe):
        files = FileManifest()
        files.add_python_resource(".", exe)

        return files

    register_target("exe", make_exe)
    register_target("resources", make_embedded_resources, depends=["exe"], default_build_script=True)
    register_target("install", make_install, depends=["exe"], default=True)

    resolve_targets()

(The above code is dedicated to the public domain and can be used without
attribution.)

From there, build/run from the config::

   $ cd python
   $ pyoxidizer build
   ...
   $ pyoxidizer run
   ...
   Python 3.8.6 (default, Oct  3 2020, 20:48:20)
   [Clang 10.0.1 ] on linux
   Type "help", "copyright", "credits" or "license" for more information.
   >>>


.. _packaging_python_executable_resource_loading_caveats:

Resource Loading Caveats
========================

PyOxidizer's configuration defaults are opinionated about how resources
are loaded by default. In the default configuration, the Python distribution's
resources are indexed and loaded via ``oxidized_importer`` at run-time.
This behavior is obviously different from what a standard ``python`` executable
would do.

If you want the built executable to behave like ``python`` would and use the
standard library importers, you can disable ``oxidized_importer`` by setting
:py:attr:`PythonInterpreterConfig.oxidized_importer` to ``False``.

Another caveat is that indexed resources are embedded in the built executable
by default. This will bloat the size of the executable for no benefit. To
disable this functionality, set
:py:attr:`PythonExecutable.packed_resources_load_mode` ``none``.

Binary Portability
==================

A ``python``-like executable built with PyOxidizer may not *just work*
when copied to another machine. See
:ref:`pyoxidizer_distributing_binary_portability`
to learn more about the portability of binaries built with PyOxidizer.