簡體   English   中英

帶有QGis的Python腳本-Python.exe停止工作

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM