.. _python-main-doc: Embedded Python ################ **Kit** comes with embedded Python. Regular **CPython 3.7** is used with no modifications. **Kit** initializes Python interpreter before any extension is started. Then each extension can add own folder (or subfolder) to ``sys.path`` (using ``[[python.module]]`` definitions). By defining ``IExt`` subclass extensions get an entry point into Python code. They can then execute any code, import other extensions, use any API they provide. More info: :ref:`exts-main-doc`. For most applications this is all you need to know about Python in **Kit**. Examining ``sys.path`` at runtime is the most common way to debug most issues. This doc provides more advanced details on Python integration. Hello Python ******************** Run ``> kit.exe --exec your_script.py`` to run your script using **Kit** Python. Using system Python ******************** When Python interpreter initialized system env vars (like ``PYTHONHOME``, ``PYTHONPATH``) are ignored. Instead following setting is used for python home: * ``/plugins/carb.scripting-python.plugin/pythonHome`` instead of `PYTHONHOME `_ .. note:: You can find default values for this setting in ``kit-core.json`` file. To use system Python installation override ``PYTHONHOME``, e.g.: ``--/plugins/carb.scripting-python.plugin/pythonHome="C:\Users\bob\AppData\Local\Programs\Python\Python37"``. Changing ``PYTHONHOME`` won't change loaded Python library. This is platform specific, but for instance on windows **Kit** is linked with ``python.dll`` and loads the one that is in the package using standard dll search rules. However standard library, ``site-packages`` and everything else will be used from specified python path. Add extra search paths ************************ To add search path (to ``sys.path``) ``/app/python/extraPaths`` setting can be used . E.g.: ``> kit.exe --/app/python/extraPaths/0="C:/temp"`` or in kit file: .. code:: toml [settings] app.python.extraPaths = ["C:/temp"] To summarize, those are all the methods to extend ``sys.path``: * Create new extension with ``[python.module]`` definitions (recommended). * Explicitly it python code ``sys.path.append(...)`` * ``/app/python/extraPaths`` setting Other Python Configuration Tweaks ********************************** Most python 'configuration variables '_ can be changed using following settings: * ``/plugins/carb.scripting-python.plugin/Py_VerboseFlag`` `Py_VerboseFlag `_ * ``/plugins/carb.scripting-python.plugin/Py_QuietFlag`` `Py_QuietFlag `_ * ``/plugins/carb.scripting-python.plugin/Py_NoSiteFlag`` `Py_NoSiteFlag `_ * ``/plugins/carb.scripting-python.plugin/Py_IgnoreEnvironmentFlag`` `Py_IgnoreEnvironmentFlag `_ * ``/plugins/carb.scripting-python.plugin/Py_NoUserSiteDirectory`` `Py_NoUserSiteDirectory `_ * ``/plugins/carb.scripting-python.plugin/Py_UnbufferedStdioFlag`` `Py_UnbufferedStdioFlag `_ * ``/plugins/carb.scripting-python.plugin/Py_IsolatedFlag`` `Py_IsolatedFlag `_ Using ``numpy``, ``Pillow`` etc. ********************************* **Kit** comes with :mod:`omni.kit.pip_archive` extension which has few popular Python modules bundled into it. Have a look inside of it on filesystem. After this extension is started you freely do ``import numpy``. Declare dependency on this extension in your extension or enable it by other means to use any of them. E.g.: run ``> kit.exe --enable omni.kit.pip_archive --exec use_numpy.py`` to run your script that can import and use ``numpy``. Using Anaconda environment ***************************** As a starting point change ``PYTHONHOME`` setting described above to point to Anaconda environment: ``--/plugins/carb.scripting-python.plugin/pythonHome="C:/Users/bob/anaconda3/envs/py37"``. It is known to work for some packages and fail for others, on case by case basis. Using other packages from pip ******************************* For most Python packages (installed with any package manager or locally developed) it is enough to add them to search path (``sys.path``). That makes them discoverable by import system. Any of methods described above can be used for that. Alternatively, **Kit** has :mod:`omni.kit.pipapi` extension to install modules from ``pip`` package manager at runtime. It will check if the package is not available and will try to pip install it and cache it. Example of usage: ``omni.kit.pipapi.install("some_package")``. After that call import installed package. Enabling the :mod:`omni.kit.pipapi` extension will allow specification of pip dependencies by extensions loaded after it. Refer to :mod:`omni.kit.pipapi` doc. At build-time any Python module can be packaged into any extension, including packages from pip. That can be done using other Python installation or kit Python. This is recommended way, so that when extension is downloaded and installed it is ready to use. There is no requirement on connectivity to public registries and no runtime cost during installation. Why some native Python modules don't work in **Kit**? ******************************************************************* It is often that something that works out of the box installed from *pip* or *Anaconda* doesn't work in **Kit**. Or vice versa **Kit** Python module doesn't load outside of **Kit**. For pure Python modules (only ``*.py`` files) finding the root cause might be a matter of following import errors. However when it involves loading native Python modules (``*.pyd`` files on windows and ``*.so`` files on linux) errors are not really helpful. Native Python modules are just regular OS shared libraries, with special **C API** that Python looks for. They also often implicitly linked with other libraries. When loaded they might not be able to find other libraries or be in conflict with already loaded libraries. Those issues can be debugged as any other library loading issues, specific to OS. Some examples are: * Exploring ``PATH``/``LD_LIBRARY_PATH`` env vars. * Exploring libraries that are already loaded by the process. * Using tools like `Dependency Walker `_. * Trying to isolate issue, by loading in a simpler or more similar environment. **Kit** doesn't do anything special in that regard and can be treated as just another instance of Python with potentially different set of loaded modules. Running **Kit** from Python **************************** Normally ``kit.exe`` process starts and loads embedded Python library. **Kit** provides Python bindings to it's core runtime components. That allows to start Python and then start **Kit** from Python. It is an experimental feature and not used often. Example of that can be found within **Kit** package: ``example.pythonapp.bat``. Difference from regular run: * Actually another Python library us used (different ``python.dll``). * That may have some GIL implications, because call stack looks differently. * Allows explicit control over update loop.