2016-06-22 175 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