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
Best Answer
arcpy.Exists only works on datasets, so it will only return whether or not a file, feature class, dataset, or feature layer (among other items) exists. Layers in an mxd are not any of those things - they're a separate class, and they reference a dataset themselves.
SO, why does it work in the Python window, but not in the standalone script? Because in ArcMap, the TOC layers are ALSO feature layers of the same dataset (effectively - they have to be in order to be displayed). arcpy.Exists("project_aoa") returns true because in addition to being a map layer, there is ALSO a feature layer of that name for it to find. In a standalone script where you open an mxd, that same thing doesn't occur, so you need to iterate over the layers (unfortunately) to find it.