So I continue to build my installer for certbot, and I would like to expose a certbot
command on Windows command line.
The relevant part of installer.cfg is the following:
[Command certbot]
entry_point=certbot.main:main
Installer is built correctly, installation behaves correctly. However, from one build + install to another, sometimes the certbot
command fails. And when it fails, it just returns failed to create process
. Nothing more, and I did not find any way to trigger some debug mode and provide more logs.
So I understood that the certbot.exe
executable, which is copied from the NSIS installer into %installdir%\bin\
, is available to the user through an injection in PATH
. Direct running of certbot.exe
leads to the same inconsistencies.
I also understood that certbot.exe
is in fact a copy of cli-{32|64}.exe
from the project https://github.com/takluyver/win_cli_launchers, that is itself a 3 years old extract of the cli-{32|64}.exe
from the well-known setuptools
project. Tried to copy the executables from a fresh and recent copy of setuptools
, same inconsistencies.
Finally, I understood that cli-{32|64}.exe
is a VisualStudio binary that reads a python script in the same folder, with the name of type cli-{32|64}-script.py
(or something-script.py
if the executable is renamed to something.exe
). It will then resolve the Python executable path from the environment or an optional shebang available at the beginning of the python script file (for instance #!C:\some\path\to\python
).
I could not succeed in repairing this behavior from the existing executables files provided by setuptools or win_cli_launchers launchers. However, I succeeded in reproducing the expected behavior with a batch file. This one:
@echo off
setlocal ENABLEDELAYEDEXPANSION
set env_dir=%~dp0
set install_dir=%env_dir:\bin\=%
set python_path=%install_dir%\Python\python.exe
set script_path=%install_dir%\bin\%~n0-script.py
set error=false
if not exist "%python_path%" 2> nul (
echo Error, python executable not found on path: %python_path%
set error=true
)
if not exist "%script_path%" 2> nul (
echo Error, python script file not found on path: %script_path%
set error=true
)
if %error%==true (
exit /b 1
)
"%python_path%" "%script_path%" %*
This batch file, assuming to be copied in the bin
directory constructed by pynsist, and assuming to be named something.bat
, will execute the python script file something-script.py
, using the Python distribution prepared by pynsist, and passing all command lines arguments to the python script file.
It is everything needed, when the bin
directory is in the user PATH
, to have a working something
command available in CLI. And this works everytime.
One question and one proposition
- Question
Is there an explanation or a process to find it, about the inconsistencies I noticed with cli.exe
?
- Proposition
We need to consider also that cli.exe
comes from the easy_install
approach of setuptools
, but the setuptools
maintainers advise to not use easy_install
anymore, because there are better alternatives. One of them is that starting with Python 3.3 for Windows, the py
launcher can start scripts with a correct interpretation of the shebang to find the correct Python environment.
But anyway the cli.exe
executable here is used only to expose CLI commands. And because the Python environment is strictly controlled and isolated using a NSIS installer, one can have the expected behavior with a simple batch file as I shown before.
So why not replacing the cli.exe
executable by a cli.bat
batch script quite similar to what I wrote ?