我购买了this book called Building Mapping Applications with 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
,但没有成功。
答案 0 :(得分:3)
我很幸运能够与这位书的作者取得联系,所以我将在这里分享他的回应:
我怀疑在看到这个之后我可能知道问题是什么 读者的问题更深入,我发现有些东西 在较新版本的QGIS中更改,示例代码不再更新 按原样写作。从技术角度来看,现在看来你 需要在调用之前实例化QApplication对象 QgsApplication.initQgis() - 本书中的示例程序 调用后实例化QApplication对象 QgsApplication.initQgis(),导致程序崩溃。修理 这样,将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为我提供了这个解决方案。
答案 1 :(得分:1)
有一件事似乎令人怀疑的是,你创建了一个gui元素而没有给它一个父级 - QgsMapCanvas()
- 然后在将它添加到布局之前尝试手动show()
它。您永远不必在子窗口小部件上调用show()
,并且所有子窗口小部件都应该是主窗口小部件(或其他子窗口小部件)的父级。
此外,您应该存储对python对象的持久引用;否则,底层C ++对象可能会被垃圾收集并导致程序崩溃。您可以通过将小部件和布局分配到self
实施例
self.layout = QVBoxLayout(...
self.layer = ...
您应该像这样添加画布,您不需要调用.show()
self.canvas = QgsMapCanvas(self)
layout.addWidget(self.canvas)