我正在运行以下内容:
for server in server_list:
for item in required_fields:
print item, eval(item)
某些密钥可能不存在,但更糟糕的是它在父密钥上表示而不是我正在扫描的密钥。
所以我正在扫描json以获取以下密钥:
server['server_management']['server_total_cost_of_ownership']['description']
哪个不存在,但它实际上是null的父级:
server['server_management']['server_total_cost_of_ownership']
如何编写代码来解释此问题?它没有给出关键错误。现在我得到以下追溯:
Traceback (most recent call last):
File "C:/projects/blah/scripts/test.py", line 29, in <module>
print item, eval(item)
File "<string>", line 1, in <module>
TypeError: 'NoneType' object has no attribute '__getitem__'
完整代码:
import csv
import json
import os
import requests
import sys
required_fields = ["server['server_name']","server['server_info']['asset_type']['display_name']",
"server['asset_status']['display_name']", "server['record_owner']['group_name']",
"server['server_management']['server_total_cost_of_ownership']['description']",
"server['server_management']['primary_business_owner']['name']",
"server['environment']['display_name']", "server['is_virtual']",
"server['managed_by']['display_name']", "server['server_info']['billable_ibm']",
"server['server_info']['billing_sub_type']['display_name']",
"server['server_info']['serial_number']", "server['location']['display_name']",
"server['inception_date']", "server['server_info']['decommission_date']" ]
# Query API for all servers
def get_servers_info():
servers_info = requests.get('url')
return servers_info.json()
def get_server_info(sid):
server_info = requests.get('url')
return server_info.json()
server_list = get_servers_info()
for server in server_list:
for item in required_fields:
print item, eval(item)
答案 0 :(得分:2)
实际上你应该避免使用eval。在您知道密钥名称之后加载json之后,您可以使用列表在树中更深入。
server['server_management']['primary_business_owner']['name']" => ["server_management', 'primary_business_owner', 'name']
这是针对必填字段列表进行json验证的片段。
data={
"d": {
"p":{
"r":[
"test"
]
}
},
"a": 3
}
def _get_attr(dict_, attrs):
try:
src = attrs[:]
root = attrs.pop(0)
node = dict_[root]
null = object()
for i, attr in enumerate(attrs[:]):
try:
node = node.get(attr, null)
except AttributeError:
node = null
if node is null:
# i+2 pop and last element
raise ValueError("%s not present (level %s)" % (attr, '->'.join(src[: i+2])))
return node
except KeyError:
raise ValueError("%s not present" % root)
# assume list of required field
reqs = [
["d", "p", "r"],
["d"],
["k"],
["d", "p", "r", "e"],
]
for req in reqs:
try:
_get_attr(data, req)
except ValueError as E:
print(E)
# prints
# k not present
# e not present (level d->p->r->e)
答案 1 :(得分:0)
忽略代码的上下文而不理解eval的使用,这样做的方法是使用.get()并使用合理的默认值对其进行种子化。
例如:
server['server_management']['server_total_cost_of_ownership']['description']
可以:
server.get('server_management', {}).get('server_total_cost_of_ownership', {}).get('description', '')
然后,如果任何一个键不存在,您将始终返回一个空的描述&#39;&#39;。
答案 2 :(得分:0)
此处的问题与使用eval
[1]完全无关。您得到的例外情况与代码直接存在的情况相同。您正在运行的内容(通过eval
)是:
a = server['server_management']
b = a['server_total_cost_of_ownership']
c = b['description']
然而,b
是None
,因此将其解析为c
将会失败。与KeyError
一样,您也可以抓住TypeError
:
for server in server_list:
for item in required_fields:
try:
print item, eval(item)
except TypeError:
print("Guess you're lucky you didn't include a fork bomb in your own code to eval.")
您当然可以选择pass
,打印违规项目,打开a browser to some page或根据输入数据执行任何适当的错误处理。
[1]虽然没有争吵,但我made a new answer that works without eval。您可以使用完全相同的错误处理:
for server in server_list:
for item in required_fields:
value = server
for key in parse_fields(field):
try:
value = value[key]
except TypeError:
print("Remember Kiddo: Eval is Evil!")
break
else: # for: else: triggers only if no break was issued
print item, value