在使用Python socket服务器时,有时会出现以下情况:当一个新的客户端连接并成功通过认证后,服务器会从数据库中获取其json编码的信息。在解码过程中,将信息存储到一个变量中。有时,对象中可能不存在某个键,这会导致出现KeyError异常,并导致整个脚本关闭。
例如,客户端向服务器发送数据包,服务器会以如下方式处理:
def handleReceiveThisPacket(self, data):
myInfo = self.info['exampleKey']
return self.send(myInfo)
如果"exampleKey"在用户的的信息中不存在(这种情况可能会发生,例如,当为新数据包添加了一个新键来处理其他内容,而用户的的信息尚未更新时),则整个脚本将关闭。虽然可以使用try、except语句来捕获异常,但在脚本中经常调用键,这样做会导致代码杂乱,到时就会有许多try和except语句。因此,有没有一种更简单的方法,让Python发出警告而不会关闭脚本,类似于PHP的处理方式? 而且,客户端是一个单独的类。
2、解决方案
方法一:使用异常处理
使用异常处理来捕获异常;为了让常规程序更简单,不需要经常检查错误,因此异常处理才存在。此外,可以使用get方法从字典中获取可选键。
def handleReceiveThisPacket(self, data):
# 如果未找到键,则返回None
myInfo = self.info.get('exampleKey')
# 如果未找到键,则返回42
myInfo = self.info.get('exampleKey', 42)
try:
return self.send(myInfo)
except Exception as e:
print("Oops an exception occurred")
print(e)
方法二:创建自定义字典类
可以创建自己的MyDict类,该类包装KeyError并记录警告:
import logging
log = logging.getLogger(__name__)
class MyDict(dict):
def __getitem__(self, key):
try:
return super(MyDict, self).__getitem__(key)
except KeyError:
log.warning('Attempted to get value for missing key %s.', str(key))
return None
d = MyDict()
d['test']
# 输出 Attempted to get value for missing key test.
或者简单地说(仅针对默认值):
from collections import defaultdict
c = defaultdict(lambda: None)
c['test']
# 输出 None
此示例返回None作为缺失键的默认值,但可以自定义它。
方法三:在更高层次处理异常
首先,PHP语言做出了许多错误的设计决策,这只是其中之一。要为Python能够以一种好的方式检测并处理这些问题而感到高兴。通常写PHP代码时,从不创建任何警告。一旦有警告,就很难区分什么是可以接受的,什么是真正的错误。
其次,可以通过多种方式处理此问题:
- 可以在更高层次(1或2而不是12)处理这些异常。
- 可以使用defaultdict。
- 可以使用实用函数。
def getkey(d, k):
try:
return d[k]
except KeyError:
return ""
请注意,所有这些解决方案都有一个严重缺陷,那就是它们会使代码变得脆弱。无法检测到键的所有可能错别字。认为最清晰的方法是使用值填充数据集以替换缺少的键,这样就无需进行任何错误处理。
方法四:使用in操作符检查集合中是否存在元素
可以使用in操作符检查集合中是否存在某个元素:
import json
o = json.loads('{"a": 1}')
"a" in o # 输出 True
"b" in o # 输出 False
o = dict(a=1)
"a" in o # 输出 True
"b" in o # 输出 False
o = (1,2,3)
1 in o # 输出 True
4 in o # 输出 False
此外,字典有一个.get(key, default=None)方法。