我在程序中使用lambda: ...
时遇到问题。由于我不希望我的TkInter GUI自动执行这些功能,我使用的是lambda
。问题是虽然Button3
导致我的程序崩溃但我不明白为什么。没有lambda它绝对没问题。这是我的代码:
import ogr, osr, sys, os
import psycopg2
import ppygis
from datetime import datetime, date
import time
import re
from Tkinter import *
import tkFileDialog
from tkFileDialog import askopenfilename # Open dialog box
from tkMessageBox import showerror
class trip_calculator:
def __init__(self):
global root
root = Tk()
def open_file_dialog():
returned_values = {}
returned_values['filename'] = askopenfilename()
Label(root, text= returned_values.get('filename')[52:] + ' selected').grid(row=2)
filepath = returned_values.get('filename')
#OPEN GPX DRIVER
driver = ogr.GetDriverByName('GPX')
datasource = driver.Open(filepath)
if datasource is None:
print 'not open'
else:
print 'open'
#GEOMETRY
datasource_layer = datasource.GetLayer(2)
#GRAB TIMESTAMPS, ELEVATION, CADENCE ETC.
datasource_layer2 = datasource.GetLayer(4)
#GRAB GEOMETRY INFORMATION AND TRANSFORM TO UTM
datasource_feature = datasource_layer.GetNextFeature()
geoSR = osr.SpatialReference()
geoSR.ImportFromEPSG(4326)
utmSR = osr.SpatialReference()
utmSR.ImportFromEPSG(32633)
coordTrans = osr.CoordinateTransformation(geoSR, utmSR)
geom = datasource_feature.GetGeometryRef()
geom1 = geom.Simplify(0)
geom.Transform(coordTrans)
geom1.Transform(coordTrans)
Label(root, text= 'geometries transformed successfully').grid(row=2, column=5)
#
# This is where the crash of Python occurs,
# `lambda: calculation(...)` won't start.
# It crashes at `features = iter(datasource_layer2)`
#
self.button3 = Button(root, text='calculate attributes', command=lambda:calculation(self,geom1,datasource_layer2)).grid(row=10, column=10, pady=10, padx=10)
def quit_me():
root.quit()
def calculation(self, geom1, datasource_layer2):
#NET AND GROSS TIME CALCULATION
timestamps_net = []
timestamps_net_helper = []
timestamps_elapsed = []
elevation_helper = []
print datasource_layer2
features = iter(datasource_layer2)
next(features)
for feature in features:
if len(timestamps_net_helper) == 2:
timestamps_net_helper = timestamps_net_helper[-1:]
timestamp = feature.GetField(4)
elevation = feature.GetField(3)
elevation_helper.append(elevation)
timestamp_stripped = timestamp[:-3]
day = timestamp[:-11]
#FOR GROSS CALCULATION
timestamps_elapsed.append(timestamp_stripped)
#FOR NET CALCULATION
timestamps_net_helper.append(timestamp_stripped)
if len(timestamps_net_helper) == 2:
#CALCULATE SECONDS BETWEEN
time_a = datetime.strptime(timestamps_net_helper[0], "%Y/%m/%d %H:%M:%S")
time_b = datetime.strptime(timestamps_net_helper[1], "%Y/%m/%d %H:%M:%S")
time_difference = time.mktime(time_b.timetuple()) - time.mktime(time_a.timetuple())
#IF SECONDS LESS THAN 20 BETWEEN GPS TIMESTAMP THEN ADD UP NET TIME
if time_difference < 20:
timestamps_net.append(time_difference)
seconds = sum(timestamps_net)
hours = seconds/60/60
time_length_net = time.strftime('%H:%M:%S', time.gmtime(seconds))
#CLIMB.....
positive_climb = []
negative_climb = []
for a, b in zip(elevation_helper, elevation_helper[1:]):
if a > 0.0 and b > 0.0:
if b > a:
positive_climb.append(b-a)
elif b == a:
pass
else:
negative_climb.append(a-b)
positive_climb = sum(positive_climb)
negative_climb = sum(negative_climb)
#GROSS (ELAPSED TIME)
start = datetime.strptime(timestamps_elapsed[0], "%Y/%m/%d %H:%M:%S")
end = datetime.strptime(timestamps_elapsed[-1], "%Y/%m/%d %H:%M:%S")
time_length = end - start
#LENGTH
length_km = float(geom1.Length()/1000)
#AVERAGE SPEED
avg_speed = (geom1.Length()/1000)/hours
#CREATE LINESTRING FOR PPYGIS AND OGR LINESTRING
myLine = ogr.Geometry(ogr.wkbLineString)
polyline = []
for z in range(geom1.GetPointCount()):
x = geom1.GetX(z)
y = geom1.GetY(z)
myLine.AddPoint(x, y)
point = ppygis.Point(x, y)
polyline.append(point)
myLine_ppy = ppygis.LineString(polyline)
Label(root, text= time_length).grid(row=10, column=5)
Label(root, text= length_km).grid(row=11, column=5)
Label(root, text= avg_speed).grid(row=12, column=5)
self.button1 = Button(root, text='browse', command= open_file_dialog).grid(row=0,pady=10, padx=25)
self.button2 = Button(root, text='close', command= quit_me).grid(row=3, pady=10, padx=25)
root.mainloop()
trip_calculator()
发生的错误是libc++abi.dylib: pure virtual method called
,但仅使用command
button3
中的lambda。任何想法如何解决这个问题?
答案 0 :(得分:2)
问题可能是由于lambda
表达式中的一些参数 - geom1
和datasource_layer2
- 是嵌套{{}的本地变量。 1}}功能,以后按下按钮并返回时不存在。
一个简单的解决方法是通过在函数返回之前的某处添加open_file_dialog()
和trip_calculator
语句来使它们成为self.datasource_layer2 = datasource_layer2
实例的属性(或者只是将它们分配给{{1}在其他地方以这种方式引用它们。)