Build Windows executable from Python 3.6 package

I have been working on a project in which I need to deploy to multiple Windows systems. I’ve written the software in Python; normally, I would clone the package repo via git to the target systems, and set up package dependencies by installing via internet, but I have some restrictions:

  • Firewalled systems can’t pull in OS-specific package dependencies
  • Firewalled systems can’t access the code repository

Which means:

  • Making changes to deployed code means hand-editing, which does not scale
  • I can copy over the entire local code repo which has cached packages for installation, but that does not scale either

So my goal is to create a single executable file which I can distribute to the target systems. I think that is the simplest, most scaleable solution.

I’m developing in a Cygwin environment, which is neither Linux nor Windows but somewhere inbetween. It is a system of POSIX-like packages that are installed on Windows and are run in a separate environment. I use it because of its similarity in feel to Linux.

My method will be to use pyinstaller to create distributable executables. I can’t build for Windows from Cygwin, so I do the following:

  • Install Python 3.6 for Windows (assuming I hadn’t before)
  • From a Windows command shell, make “virtualenv” available to the system with
    • python -m pip install virtualenv
  • Create a Windows-compatible virtual Python environment (3.6) in my Python package folder. Virtual environments create portable, self-contained instances of the Python interpreter and dependent packages are installed in that scope
    • virtualenv package_base_folder
    • Specify a version if multiple are installed: virtualenv –python=python3.6 package_base_folder
  • Change directory into the package folder, and activate the virtual environment with
    • .\Scripts\activate

At this point, the system should look to the package_base_folder\Scripts path for the Python interpreter executable file. Dependencies installed via pip are accessible to the virtual environment’s version of Python. If for some reason the “activate” script failed, I can still use Python in the virtual environment by referring to its path:

  • .\Scripts\python.exe -m pip list

I continue:

  • Install my Python software’s requirements like so
  • Install “pyinstaller” which will analyze the Python file that I want to convert to Windows executable
    • .\Scripts\python.exe -m pip install pyinstaller
  • Run the installer on my main Python script
    • .\Scripts\pyinstaller.exe module_folder\my_python_file.py

At this point pyinstaller produces a LOT of console output, most of it is informational and for debugging purposes. It creates a distributable executable in module_folder\dist. Then I can pass around this executable to the other systems that I want to run it on.

Of course, a good developer tests to make sure everything works as expected, and that there are no OS-specific errors present in Windows that aren’t present in other systems!