@@ -17,13 +17,13 @@ integrates much better with the operating system if the application is delivered
1717as a native Windows executable. However, Python is not a natively compiled
1818language, and so does not create executables by default.
1919
20- The normal way around this issue is to make your Python code into a library, and
21- declare one or more " script entry points" for the library. When the library is
22- installed, the installer will generate a native executable which invokes the
23- Python interpreter, calling your entry point function. This is a very effective
24- solution, and is used by many Python applications. It is supported by utilities
25- such as ``pipx `` and ``uv tool ``, which make managing such entry points (and the
26- virtual environments needed to support them) easy.
20+ One way around this issue is to make your Python code into a library, and
21+ declare one or more :ref: ` script entry points < script-entry-points >` for the
22+ library. When the library is installed, the installer will provide an executable
23+ which invokes the Python interpreter, calling your entry point function. This is
24+ a very effective solution, and is used by many Python applications. It is
25+ supported by utilities such as ``pipx `` and ``uv tool ``, which make managing
26+ such entry points (and the virtual environments needed to support them) easy.
2727
2828There are, however, some downsides to this approach. The entry point wrapper
2929results in a chain of processes being created - the wrapper itself, the virtual
@@ -90,10 +90,27 @@ need to do is make a small modification to the wrapper code.
9090Your code can use 3rd party dependencies freely. These will be installed along
9191with your application.
9292
93- When you are ready to build your application, you can install the Python code
94- using::
93+ You can create your application code in whatever way you prefer - there is no
94+ particular need to make it buildable as a wheel. For the purposes of this
95+ discussion, we will assume one of two project layouts:
9596
96- pip install --target "<Application directory>\lib" MyAwesomePythonApp
97+ 1. A project which can be installed via ``pip install ``, with all of its
98+ dependencies listed in the ``pyproject.toml `` file, as normal.
99+ 2. A Python application stored in a local directory. In this case, third party
100+ dependencies are listed in a ``requirements.txt `` file.
101+
102+ When you are ready to build your application, you need to copy all of the
103+ required code and dependencies into the ``lib `` directory of the application.
104+ For case (1), this can be done using::
105+
106+ pip install --target "<Application directory>\lib" .
107+
108+ For case (2), you should copy your application code into the ``lib `` directory
109+ and then run::
110+
111+ pip install --target "<Application directory>\lib" -r requirements.txt
112+
113+ to install the 3rd party dependencies.
97114
98115You can then run your application as follows::
99116
@@ -154,6 +171,10 @@ application code should look like the following::
154171 /* Include the Python headers */
155172 #include <Python.h>
156173
174+ #define PYTHON_LOCATION L"interp"
175+ #define APP_MODULE "MyAwesomePythonApp"
176+ #define APP_FUNCTION "main"
177+
157178 /* Finding the Python interpreter */
158179 #include <windows.h>
159180 #include <pathcch.h>
@@ -188,7 +209,7 @@ application code should look like the following::
188209 * This MUST be called before any functions from the Python
189210 * runtime are called.
190211 */
191- if (!dll_dir(L"interp" ))
212+ if (!dll_dir(PYTHON_LOCATION ))
192213 return -1;
193214
194215 /* Initialise the Python configuration */
@@ -214,10 +235,10 @@ application code should look like the following::
214235 */
215236
216237 int exitCode = -1;
217- PyObject *module = PyImport_ImportModule("MyAwesomePythonApp" );
238+ PyObject *module = PyImport_ImportModule(APP_MODULE );
218239 if (module) {
219240 // Pass any more arguments here
220- PyObject *result = PyObject_CallMethod(module, "main" , NULL);
241+ PyObject *result = PyObject_CallMethod(module, APP_FUNCTION , NULL);
221242 if (result) {
222243 exitCode = 0;
223244 Py_DECREF(result);
@@ -342,8 +363,16 @@ needs a GUI, the simplest option is likely to be to use one of the other GUI
342363frameworks available from PyPI, such as PyQt or wxPython.
343364
344365If your only option is tkinter, you will need to add a copy to the embedded
345- distribution, or use a different distribution. Both of these options are outside
346- the scope of this guide, however.
366+ distribution. You can get the relevant files from a full Python installation
367+ (which must be the same version as you're using for your application). The
368+ files you need are:
369+
370+ * ``_tkinter.pyd ``, ``tcl*.dll ``, ``tk*.dll `` and ``zlib1.dll `` from
371+ ``{sys.prefix}\DLLs ``
372+ * The ``tcl `` directory from ``{sys.prefix} ``
373+ * The ``tkinter `` directory from ``{sys.prefix}\Lib ``
374+
375+ You should copy all of these into your embedded interpreter directory.
347376
348377Subprocesses and ``sys.executable ``
349378-----------------------------------
@@ -373,7 +402,7 @@ positive side, though, operating systems other than Windows have less need for
373402this, as support for interpreted code as applications is generally better. In
374403particular, on Unix a Python file with a "shebang" line is treated as a
375404first-class application, and there is no benefit to making a native
376- appliocation .
405+ application .
377406
378407So while this discussion is specific to Windows, the problem it is solving is
379408*also * unique to Windows.
0 commit comments