Typ einer Variablen bestimmen
Mit Schnittstelle meine ich, dass hier 1 hausinternes Programm Datensätze übergibt, die nunmal in diesem eigenen Format aufgebaut sind. Änderbar ist das nicht, muss als gegeben hingenommen werden. Es richtet sich aber nach keinem Standard...
Vielleicht aber trotzdem JSON probieren. Die nicht-kompatiblen Strings lässt man halt so stehen, wie sie sind:
Zumindest für dein Beispiel klappt das ganz gut:
Leider bringt `json.loads()` keinen `error`-Paramter mit, wo man eine Standardbehandlung für ungültige Typen definieren könnte. Dann wäre das Ganze nämlich mit einer simplen List Comprehension implementierbar.
Code: Alles auswählen
import json
def strings_to_objects(strings):
for s in strings:
try:
result = json.loads(s)
except ValueError:
result = s
yield result
Code: Alles auswählen
In [43]: list(strings_to_objects(a_list))
Out[43]: ['auto', 17, [u'eine liste', 42], {u'HAUS': 50, u'TEST': 40}]
- Hyperion
- Moderator
- Beiträge: 7478
- Registriert: Freitag 4. August 2006, 14:56
- Wohnort: Hamburg
- Kontaktdaten:
Hm... das ist natürlich doof und man kann da wenig machen Man fragt sich nur, was den ursprünglichen Entwickler getrieben hat, so ein eigenes Format zu generieren...
Edit: Grad noch gesehen. snafus Idee ist vielleicht gar nicht so verkehrt!
Edit: Grad noch gesehen. snafus Idee ist vielleicht gar nicht so verkehrt!
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
assert encoding_kapiert
Wobei schon interesant wäre zu wissen, ob das Format Python-artig (`None`, `True`, ...) oder JSON-artig (`null`, `true`) ist. Generell finde ich jetzt nicht, dass soviel gegen die Anwendung von besagtem `literal_eval()` spricht, sofern der Input Python-Code ist bzw falls die uneinheitlichen Typbezeichnungen garnicht vorkommen.
Einen wirklich schönen Weg kann man bei einem nicht-standardisierten Format eh nicht gehen...
Einen wirklich schönen Weg kann man bei einem nicht-standardisierten Format eh nicht gehen...
- pillmuncher
- User
- Beiträge: 1484
- Registriert: Samstag 21. März 2009, 22:59
- Wohnort: Pfaffenwinkel
api hat geschrieben:Nun muss ich in Abhängigkeit des Typs des Inhaltes des Strings verschiedene Dinge tun. Also so in der Form...
wenn vom Typ 'String' dann tue ...
wenn vom Typ 'Int' dann tue ...
Code: Alles auswählen
class Visitor(object):
def __init__(self):
self.indent = 0
def spaces(self):
return ' ' * (4 * self.indent)
def visit(self, visitable):
getattr(self, u'visit_' + type(visitable).__name__)(visitable)
def visit_list(self, alist):
print self.spaces() + 'list:'
self.indent += 1
for each in alist:
self.visit(each)
self.indent -= 1
def visit_dict(self, adict):
print self.spaces() + 'dict:'
self.indent += 1
for key, value in adict.iteritems():
self.visit_pair(key, value)
self.indent -= 1
def visit_pair(self, key, value):
print self.spaces() + 'pair:', repr(key), ':', repr(value)
def visit_int(self, anint):
print self.spaces() + 'int:', repr(anint)
def visit_str(self, astr):
try: # Obacht!
# Das wird nicht immer funktionieren, und zudem ist es gefährlich, su.:
item = eval(astr)
except (NameError, SyntaxError):
print self.spaces() + 'string:', repr(astr)
except:
raise
else:
self.visit(item)
a_list = ['auto', '17', '["eine liste", 42]', '{"TEST":40, "HAUS": 50}']
visitor = Visitor()
visitor.visit(a_list)
Code: Alles auswählen
list:
string: 'auto'
int: 17
list:
string: 'eine liste'
int: 42
dict:
pair: 'TEST' : 40
pair: 'HAUS' : 50
Das Problem bei der ganzen Angelegenheit ist, wie schon erwähnt wurde, dass dein Datenformat Strings enthält, die für sich selbst stehen, und solche, die für Programmcode stehen. Angenommen, du verwendest in deinem Programm eine globale Variable namens TEST, wie willst du dann entscheiden, ob mit dem String 'TEST' diese Variable gemeint ist, oder ob es sich um einen String handelt, der nur zufällig aus genau derselben Buchstabenfolge besteht wie der Variablenname? Oder, noch schlimmer, was wenn der String aus der Buchstabenfolge '__import__("subprocess").call(["rm", "-rf", "/"])' oä. besteht?
In specifications, Murphy's Law supersedes Ohm's.
pillmuncher: Was spricht dagegen, statt eval ast.literal_eval zu verwenden?
- pillmuncher
- User
- Beiträge: 1484
- Registriert: Samstag 21. März 2009, 22:59
- Wohnort: Pfaffenwinkel
Du meinst so?derdon hat geschrieben:pillmuncher: Was spricht dagegen, statt eval ast.literal_eval zu verwenden?
Code: Alles auswählen
def visit_str(self, astr):
try:
item = ast.literal_eval(astr)
except (NameError, SyntaxError, ValueError):
print self.spaces() + 'string:', repr(astr)
except:
raise
else:
self.visit(item)
In specifications, Murphy's Law supersedes Ohm's.