2016-06-22 130 views
1

我購買this book called Building Mapping Applications with QGIS,我正在嘗試通過其中一個練習。有一個腳本,我嘗試運行,崩潰python,生成錯誤消息「python.exe已停止工作」。Python腳本與QGis - 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() 

我不知道Python與QGIS有很多關係,所以我不太確定是什麼導致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沒有成功。

回答

3

我很幸運取得聯繫,與書的作者,所以我將分享他的反應在這裏:

我懷疑我可能知道是什麼問題...更深入地看着這 讀者的問題後,我發現有些事情 在QGIS的新版本中進行了更改,並且示例代碼不再是 按原樣編寫。從技術角度看,您現在需要在調用 之前實例化QApplication對象QgsApplication.initQgis() - 中示例程序在調用 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() 

正如你所看到的,我已經搬到了 「應用=的QApplication(sys.argv中)」 行頂端。

重要提示:確保向前斜線在viewer = MapViewer("C:/folder/shapefile.shp")使用 - 用一個反斜槓會導致錯誤消息,指出shape文件是無效的。

我還認爲值得一提的是,上述修復(對問題的評論)都不是必須的。所以,如果路徑中定義的腳本將工作如下:

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殼牌:

python "C:\script.py"

最後,請注意,在撰寫本文時,腳本正常工作並啓動顯示引用的shapefile的查看器,但是re原來的殼了一些錯誤,似乎沒有成爲問題:

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 

許多感謝作者埃裏克Westra爲我提供這個解決方案。

1

有一件似乎可疑的事情是,您正在創建一個gui元素而沒有給它父母 - QgsMapCanvas() - 然後嘗試在將它添加到佈局之前手動將它show()。您不應該在子小部件上調用show(),並且所有子小部件都應該用於主小部件(或其中一個子小部件)。

此外,你應該存儲持久引用的python對象;否則,底層C++對象可能會收集垃圾並導致程序崩潰。您可以通過將您的小部件和佈局分配給屬性self

Ex。

self.layout = QVBoxLayout(... 
self.layer = ... 

你應該加入這樣的畫布,你不應該需要調用.show()

self.canvas = QgsMapCanvas(self) 
layout.addWidget(self.canvas) 
+0

就像一個參考文獻,我沒有寫這個腳本,它是本應該工作而不做任何改變的直接副本。聽起來好像我需要對腳本進行多種修改才能解決這些問題。我刺了一刀,但我似乎沒有得到任何地方。如果你有任何其他的指導意見,我會很感激。或者,如果你準備好了,我會很樂意嘗試你的腳本的修改版本! – ge0m3try