[GIS] Working Windows Standalone .EXE From QGIS Python Script Using PyInstaller

pyqgispythonqgisstandalone

Has anyone been able to create a working standalone Windows .EXE file from a QGIS Python Script Using PyInstaller?

Best Answer

I managed to get it working by updating the .spec file to copy the missing qgis plugin folder into the .exe bundle. I also had to add a check in the code to see if i'm running bundled so I can choose the correct path to the bundled qgis_plugins folder. I assume a better long term fix would be to make this into a runtime hook but for now this is sufficient.

Here is the code to check the whether bundled or not...

def setup_qgis(self):
    ''' Set QGIS paths based on whether running as a bundled application or not '''
    if getattr(sys,'frozen',False):
        print "Running In An Application Bundle"
        bundle_dir = sys._MEIPASS
        qgis_prefix_path = bundle_dir
        qgis_plugin_path = bundle_dir + '\qgis_plugins'
    else:
        print "Running In A Normal Python Environment"
        bundle_dir = os.path.dirname(os.path.abspath(__file__))
        qgis_prefix_path = os.getenv("QGIS_PREFIX_PATH")
        qgis_plugin_path = qgis_prefix_path + '\plugins'
    QgsApplication.setPrefixPath(qgis_prefix_path, True)
    QgsApplication.setPluginPath(qgis_plugin_path)
    QgsApplication.initQgis()
    registry = QgsProviderRegistry.instance()
    if not 'ogr' in registry.providerList():
        print 'ERROR: Missing OGR provider'

Here is the One File spec file contents...

# -*- mode: python -*-
block_cipher = None
a = Analysis(['ShapeViewer.py'],
         pathex=['c:\\Users\\Daniel Stephanson\\workspace\\ShapeViewer'],
         binaries=None,
         datas=[('c:/OSGeo4W64/apps/qgis/plugins/*.dll','qgis_plugins')],
         hiddenimports=['PyQt4.QtSql','PyQt4.QtNetwork','PyQt4.QtXml','PyQt4.Qsci'],
         hookspath=None,
         runtime_hooks=None,
         excludes=None,
         win_no_prefer_redirects=None,
         win_private_assemblies=None,
         cipher=block_cipher)
pyz = PYZ(a.pure, a.zipped_data,
         cipher=block_cipher)
exe = EXE(pyz,
      a.scripts,
      a.binaries,
      a.zipfiles,
      a.datas,
      name='ShapeViewer',
      debug=False,
      strip=None,
      upx=True,
      console=False)

Here are the CLI commands...

Create a command CLI window by running the OSGeo4W.bat file in the C:\OSGeo4W64 directory then update the path as follows...

set PATH=C:\OSGeo4W64\apps\qgis\bin;%PATH%

Set the PYTHONPATH variable in a command prompt to include the bin directory of the QGIS installation...

set PYTHONPATH=C:\OSGeo4W64\bin;C:\OSGeo4W64\apps\qgis\python;C:\OSGeo4W64\apps\qgis\python\plugins;C:\OSGeo4W64\apps\Python27\lib\site-packages;

Create the .exe using PyInstaller with the .spec file...

pyinstaller --clean -F -d -y ShapeViewer.spec
Related Question