Android sl4a, TypeError, no attribute __getitem__

Python in C/C++ embedden, C-Module, ctypes, Cython, SWIG, SIP etc sind hier richtig.
Antworten
JonnyDamnnox
User
Beiträge: 68
Registriert: Sonntag 10. März 2013, 21:14

Hallo,
Ich arbeite grade ein Buch über den scripting layer for android durch, und ich glaub bei einem Beispiel ist ein Fehler im code :

Das skript soll das Handy in den silent modus schalten sobald man sich an einem bestimmten Ort befindet, der per GPS geortet wird:

Code: Alles auswählen

from math import *
#berechnet den Abstand zwischen zwei Punkten

def haversine(lon1, lat1, lon2, lat2):
	"""
	Calculate the great circle distance between two points
	on the earth (specified in decimal degrees)
	"""
	#convert decimal degrees to radians
	lon1, lat1, lon2, lat2 = map(radiants, [lon1, lat1, lon2, lat2])
	#haversine formula
	dlon = lon2 - lon1
	dlat = lat2 - lat1
	a = sin(dlat/2)**2 + cos(lat1) * cos(lat2) * sin(dlon/2)**2
	c = 2 * atan2(sqrt(a), sqrt(1-a))
	km = 6367 * c
	return km
	
import android, time
droid = android.Android()

lat1 = 33.111111
lon1 = 90.000000

droid.startLocating()

time.sleep(15)
while True:
	loc = droid.readLocation().result
	if loc == {}:
		loc = droid.getLastKnownLocation().result
	if loc != {}:
		try:
			n = loc["gps"]
		except KeyError:
			n = loc["network"]
	la = n["latitude"]
	lo = n["longitude"]
	
	if haversine(la, lo, lat1, lon1) < 1:
		droid.toggleRingerSilentMode(True)
	else:
		droid.toggleRingerSilentMode(False)
Fehlermeldung:
line 36 (das ist die Zeile : la=n["latitude"])
TypeError: "NoneType" object has no attribute "__getitem__"

Ich weiß das dieser Fehler bedeutet das irgendwo ein Wert 0 gesetzt wird ! Leider hab ich keine Ahnung was falsch ist .

Einen Fehler(im code aus dem Buch) hatte ich schon entdeckt. Aber irgendwas stimmt immer noch nicht :K


gruß
BlackJack

@JonnyDamnnox: Ganz offensichtlich ist `n` an der Stelle `None`. Das bedeutet, dass `loc` entweder unter dem Schlüssel 'gps' oder 'network' den Wert `None` gespeichert hat. Finde mal heraus unter welchem Schlüssel das ist. Wahrscheinlich erlaubt die API auch das ein Schlüssel vorhanden, aber der Wert `None` ist. Dagegen müsste man dann also auch prüfen.

Der Code ist allerdings nicht gut. Es kann durchaus sein, dass `n` überhaupt nicht definiert wurde, wenn das erste mal darauf zugegriffen wird. Namen wie `n`, `la`, und `lo` sind schlecht, weil sie den Leser unnötig zum Nachdenken oder Raten zwingen. Selbst für `loc` könnte man das eventuell sagen.

Das ``if``/``else`` am Ende ist unnötig kompliziert, weil die Bedingung beim ``if`` ja schon einen Wahrheitswert liefert, den man als Argument für den Aufruf von `toggleRingerSilentMode()` verwenden kann.
JonnyDamnnox
User
Beiträge: 68
Registriert: Sonntag 10. März 2013, 21:14

Hallo BlackJack, danke für die Antwort :)

Die Werte liefern beide "none" aus. Ich habe kein GPS eingeschaltet(deswegen result={}) von daher springt er gleich auf lastknownlocation und von da gleich auf network. "gps" und "network" sind "none":

Code: Alles auswählen

...
droid.getLastKnownLocation()
Result(id=1, result={u'passive': None, u'network': None, u'gps':None}, error=None)

Allerdings müsste doch in jedem Fall eine latitude und eine longitude angegeben werden. Aber es existiert auch kein dictionary Eintrag von "network" oder "gps" dazu. Also ich muss dazu sagen das die im Buch ein ältere Version vom sl4a benutzen. Vielleicht liegts daran, oder an meinen Netzwerk/GPS Einstellungen??

Gruß
BlackJack

@JonnyDamnnox: Wenn weder über WLAN noch über GPS eine Position ermittelt wurde, welche Position sollte die Funktion denn dann zurück geben? Raten? Würfeln? Du musst halt im Programm auch den Fall berücksichtigen, dass (noch) gar keine Position ermittelt wurde und dementsprechend auch nicht zurück gegeben werden kann.
JonnyDamnnox
User
Beiträge: 68
Registriert: Sonntag 10. März 2013, 21:14

hmpf ich hatte wohl alles ausgeschaltet :roll: . Habs aber jetzt nicht noch mal getestet. Trotzdem danke für die Hilfe !

Gruß
Antworten