[英]Python Script with QGis - Python.exe Stopped Working
我購買了這本書,即《使用QGIS構建地圖應用程序》,並且正在嘗試完成其中一項練習。 我嘗試運行一個腳本,該腳本使python崩潰,並生成錯誤消息“ python.exe已停止工作”。
import sys
import os
from qgis.core import *
from qgis.gui import *
from PyQt4.QtGui import *
from PyQt4.QtCore import Qt
#############################################################################
class MapViewer(QMainWindow):
def __init__(self, shapefile):
QMainWindow.__init__(self)
self.setWindowTitle("Map Viewer")
canvas = QgsMapCanvas()
canvas.useImageToRender(False)
canvas.setCanvasColor(Qt.white)
canvas.show()
layer = QgsVectorLayer(shapefile, "layer1", "ogr")
if not layer.isValid():
raise IOError("Invalid shapefile")
QgsMapLayerRegistry.instance().addMapLayer(layer)
canvas.setExtent(layer.extent())
canvas.setLayerSet([QgsMapCanvasLayer(layer)])
layout = QVBoxLayout()
layout.addWidget(canvas)
contents = QWidget()
contents.setLayout(layout)
self.setCentralWidget(contents)
#############################################################################
def main():
""" Our main program.
"""
QgsApplication.setPrefixPath(os.environ['QGIS_PREFIX'], True)
QgsApplication.initQgis()
app = QApplication(sys.argv)
viewer = MapViewer("C:/folder/shapefile.shp")
viewer.show()
app.exec_()
QgsApplication.exitQgis()
#############################################################################
if __name__ == "__main__":
main()
我對使用QGIS的Python不太了解,所以我不太確定是什么導致python崩潰。 我確信所有模塊都可以正確導入,因為如果我定義了路徑,然后使用OSGeo4W Shell在腳本中導入了模塊,則不會出現錯誤消息。
這是定義我的路徑的方式:
SET OSGEO4W_ROOT=C:\OSGeo4W64
SET QGIS_PREFIX=%OSGEO4W_ROOT%\apps\qgis
SET PATH=%PATH%;%QGIS_PREFIX%\bin
SET PYTHONPATH=%QGIS_PREFIX%\python;%PYTHONPATH%
考慮到所有這些,我認為腳本中肯定有錯誤。 但是,當我使用http://pep8online.com/檢查腳本時,沒有我可以修復的錯誤,這將導致python不崩潰。
請注意,我已經嘗試過嘗試SET PATH=%QGIS_PREFIX%\\bin;%PATH%
而不是SET PATH=%PATH%;%QGIS_PREFIX%\\bin
,但沒有成功。
我很幸運能與這本書的作者取得聯系,因此我將在這里分享他的回答:
我懷疑我可能知道問題出在哪里……在更深入地研究了讀者的問題之后,我發現新版本的QGIS中發生了一些變化,並且示例代碼在編寫時不再起作用。 用技術術語來說,現在看來您需要在調用QgsApplication.initQgis()之前實例化QApplication對象-書中的示例程序在調用QgsApplication.initQgis()之后實例化QApplication對象。崩潰。 要解決此問題,請將main()函數更改為如下所示:
def main():
""" Our main program.
"""
app = QApplication(sys.argv)
QgsApplication.setPrefixPath(os.environ['QGIS_PREFIX'],True)
QgsApplication.initQgis()
viewer = MapViewer("C:/folder/shapefile.shp")
viewer.show()
app.exec_()
QgsApplication.exitQgis()
如您所見,我已經將“ app = QApplication(sys.argv)”行移到頂部。
重要說明:確保在viewer = MapViewer("C:/folder/shapefile.shp")
使用正斜杠-使用反斜杠將導致錯誤消息,指出shapefile無效。
我還認為值得一提的是,以上修復方法(對該問題的評論)都沒有必要。 因此,如果路徑定義如下,腳本將起作用:
SET OSGEO4W_ROOT=C:\OSGeo4W64
SET QGIS_PREFIX=%OSGEO4W_ROOT%\apps\qgis
SET PATH=%PATH%;%QGIS_PREFIX%\bin
SET PYTHONPATH=%QGIS_PREFIX%\python;%PYTHONPATH%
然后,整個腳本如下所示:
import sys
import os
from qgis.core import *
from qgis.gui import *
from PyQt4.QtGui import *
from PyQt4.QtCore import Qt
#############################################################################
class MapViewer(QMainWindow):
def __init__(self, shapefile):
QMainWindow.__init__(self)
self.setWindowTitle("Map Viewer")
canvas = QgsMapCanvas()
canvas.useImageToRender(False)
canvas.setCanvasColor(Qt.white)
canvas.show()
layer = QgsVectorLayer(shapefile, "layer1", "ogr")
if not layer.isValid():
raise IOError("Invalid shapefile")
QgsMapLayerRegistry.instance().addMapLayer(layer)
canvas.setExtent(layer.extent())
canvas.setLayerSet([QgsMapCanvasLayer(layer)])
layout = QVBoxLayout()
layout.addWidget(canvas)
contents = QWidget()
contents.setLayout(layout)
self.setCentralWidget(contents)
#############################################################################
def main():
""" Our main program.
"""
app = QApplication(sys.argv)
QgsApplication.setPrefixPath(os.environ['QGIS_PREFIX'],True)
QgsApplication.initQgis()
viewer = MapViewer("C:/folder/shapefile.shp")
viewer.show()
app.exec_()
QgsApplication.exitQgis()
#############################################################################
if __name__ == "__main__":
main()
使用以下命令在OSGEO4W Shell中執行它:
python "C:\\script.py"
最后,請注意,在撰寫本文時,腳本可以正常工作,並啟動查看器以顯示所引用的shapefile,但在shell中返回一些似乎沒有問題的錯誤:
ERROR: Opening of authentication db FAILED
ERROR: Unable to establish authentication database connection
ERROR: Auth db could not be created and opened
QSqlDatabasePrivate::database: unable to open database: "unable to open database file Error opening database"
ERROR: Opening of authentication db FAILED
非常感謝作者Erik Westra為我提供了此解決方案。
似乎令人懷疑的一件事是,您在創建gui元素時沒有為其賦予父元素QgsMapCanvas()
-,然后嘗試在將其添加到布局之前手動對其進行show()
。 您永遠不必在子小部件上調用show()
,並且所有子小部件都應作為主窗口小部件(或其其他子窗口小部件之一)的父級。
另外,您應該存儲對python對象的持久引用; 否則,底層的C ++對象可能會被垃圾回收並導致程序崩潰。 您可以通過將小部件和布局分配給self
的屬性來self
例如
self.layout = QVBoxLayout(...
self.layer = ...
您應該像這樣添加畫布,而無需調用.show()
self.canvas = QgsMapCanvas(self)
layout.addWidget(self.canvas)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.