Montag, 8. Februar 2010

Distributing python apps for the windows platform

So you've kept your python code platform independent and struggled through the process of generating windows executables via a py2exe aware setup.py script? Congratulations - you're ready to create a setup package! But if using a python version >2.6 you'll have to solve the visual C++ runtime issues! Python and your derived apps are linked against VC libraries and contain a version specification (called "assemblies") to access the correct set of DLLs. You can fetch that XML coded info from your python exe or dll files using my script getassembly.py and it will look like this:

<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
  <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
    <security>
      <requestedPrivileges>
        <requestedExecutionLevel level="asInvoker" uiAccess="false"></requestedExecutionLevel>
      </requestedPrivileges>
    </security>
  </trustInfo>
  <dependency>
    <dependentAssembly>
      <assemblyIdentity type="win32" name="Microsoft.VC90.CRT" version="9.0.21022.8" processorArchitecture="x86" publicKeyToken="1fc8b3b9a1e18e3b"></assemblyIdentity>
    </dependentAssembly>
  </dependency>
</assembly>

Howto locate required VC DLLs

  • Download getassembly.py into a folder of your choice.
  • Using the windows console execute (make sure to adjust the paths):
    >cd C:\path\to\getassembly
    >python getassembly.py C:\python26\python.exe
  • In the output you'll find the dependentAssembly that holds all information you need to find the correct folder for copying the correct set of DLLs:
    <dependentAssembly>
        <assemblyIdentity type="win32" name="Microsoft.VC90.CRT"
        version="9.0.21022.8" processorArchitecture="x86"
        publicKeyToken="1fc8b3b9a1e18e3b"></assemblyIdentity>
    </dependentAssembly>
  • In the example above this would be on my system:
    C:\WINDOWS\WinSxS\x86_Microsoft.VC90.CRT_1fc8b3b9a1e18e3b_9.0.21022.8_x-ww_d08d0375

You have two packaging options to fullfill the dependencies listed in the manifest:
  1. Install Microsoft.VC90.CRT.manifest, msvcp90.dll and msvcr90.dll as a "private assembly" into the application directory (provided that you have the license to distribute those files).
  2. Preferred: Include the redistributable installer vcredist_x86.exe. It will setup a shared "side by side assembly" into the Windows\WinSxS system directory.
For options on how to perform a silent install read Aaron Stebner's WebLog. Here's my recipe for implementing this in an Inno Setup script: Put this code into the corresponding [files] and [run] sections. Be sure to fix Source: {#MySourceDir}\shared so that it points to vcredist_x86.exe on your system.
[files]
Source: {#MySourceDir}\shared\vcredist_x86.exe; DestDir: {tmp}; Permissions: everyone-full; Flags: ignoreversion overwritereadonly
;...additional [files] options

[run]
Filename: {tmp}\vcredist_x86.exe; Parameters: /qb!; WorkingDir: {tmp}; StatusMsg: Checking for and installing Microsoft Visual C++ Redistributable Package...; Flags: waituntilterminated
;...additional [run] options
This was successfully tested on Windows XP, Vista and 7 with a simple wx application - a stoichiometric calculator. You can download the full source here.