gpt4 book ai didi

python - 我应该如何正确处理Python3中的异常

转载 作者:太空狗 更新时间:2023-10-29 17:39:31 25 4
gpt4 key购买 nike

我不明白我应该在这里和现在处理什么类型的异常,我应该重新提出什么类型的异常或者不在这里处理,以及以后(在更高层)如何处理它们。例如:我使用python3和ssl通信编写了客户机/服务器应用程序。客户机应该验证文件之间的差异,如果存在差异,那么它应该将这个“更新”的文件发送到服务器。


class BasicConnection:
#blablabla
def sendMessage(self, sock, url, port, fileToSend, buffSize):
try:
sock.connect((url, port))
while True:
data = fileToSend.read(buffSize)
if not data: break
sock.send(data)
return True
except socket.timeout as toErr:
raise ConnectionError("TimeOutError trying to send File to remote socket: %s:%d"
% (url,port)) from toErr
except socket.error as sErr:
raise ConnectionError("Error trying to send File to remote socket: %s:%d"
% (url,port)) from sErr
except ssl.SSLError as sslErr:
raise ConnectionError("SSLError trying to send File to remote socket: %s:%d"
% (url,port)) from sslErr
finally:
sock.close()

在Python中使用异常是正确的方法吗?问题是:如果file.read()抛出ioerror怎么办?我应该在这里处理它,还是什么都不做,稍后再处理?还有许多其他可能的例外?
客户端使用此类(basicConnection)将更新的文件发送到服务器:

class PClient():
def __init__(self, DATA):
'''DATA = { 'sendTo' : {'host':'','port':''},
'use_ssl' : {'use_ssl':'', 'fileKey':'', 'fileCert':'', 'fileCaCert':''},
'dirToCheck' : '',
'localStorage': '',
'timeToCheck' : '',
'buffSize' : '',
'logFile' : ''} '''
self._DATA = DATA
self._running = False
self.configureLogging()


def configureLogging(self):
#blablabla

def isRun(self):
return self._running

def initPClient(self):
try:
#blablabla

return True
except ConnectionError as conErr:
self._mainLogger.exception(conErr)
return False
except FileCheckingError as fcErr:
self._mainLogger.exception(fcErr)
return False
except IOError as ioErr:
self._mainLogger.exception(ioErr)
return False
except OSError as osErr:
self._mainLogger.exception(osErr)
return False


def startPClient(self):
try:
self._running = True
while self.isRun():
try :
self._mainLogger.debug("Checking differences")
diffFiles = FileChecker().checkDictionary(self._dict)

if len(diffFiles) != 0:
for fileName in diffFiles:
try:
self._mainLogger.info("Sending updated file: %s to remote socket: %s:%d"
% (fileName,self._DATA['sendTo']['host'],self._DATA['sendTo']['port']))
fileToSend = io.open(fileName, "rb")
result = False
result = BasicConnection().sendMessage(self._sock, self._DATA['sendTo']['host'],
self._DATA['sendTo']['port'], fileToSend, self._DATA['buffSize'])
if result:
self._mainLogger.info("Updated file: %s was successfully delivered to remote socket: %s:%d"
% (fileName,self._DATA['sendTo']['host'],self._DATA['sendTo']['port']))
except ConnectionError as conErr:
self._mainLogger.exception(conErr)
except IOError as ioErr:
self._mainLogger.exception(ioErr)
except OSError as osErr:
self._mainLogger.exception(osErr)

self._mainLogger.debug("Updating localStorage %s from %s " %(self._DATA['localStorage'], self._DATA['dirToCheck']))
FileChecker().updateLocalStorage(self._DATA['dirToCheck'],
self._DATA['localStorage'])
self._mainLogger.info("Directory %s were checked" %(self._DATA['dirToCheck']))
time.sleep(self._DATA['timeToCheck'])
except FileCheckingError as fcErr:
self._mainLogger.exception(fcErr)
except IOError as ioErr:
self._mainLogger.exception(ioErr)
except OSError as osErr:
self._mainLogger.exception(osErr)
except KeyboardInterrupt:
self._mainLogger.info("Shutting down...")
self.stopPClient()
except Exception as exc:
self._mainLogger.exception(exc)
self.stopPClient()
raise RuntimeError("Something goes wrong...") from exc

def stopPClient(self):
self._running = False

对吗?也许有人会花自己的时间来帮助我理解处理异常的蟒蛇式风格?我不明白如何处理这些异常,如nameerror、typeerror、keyerror、valueerror…等等。它们可以在任何时候被抛出到任何语句中…如果我想记录下所有的信息,那么如何处理它们呢?
人们通常应该记录哪些信息?如果发生错误,我应该记录关于它的什么信息?所有的追溯,或只是有关它的相关信息或其他什么?
我希望有人能帮助我。
谢谢。

最佳答案

一般来说,您应该“捕获”期望发生的异常(因为它们可能是由用户错误或程序控制之外的其他环境问题引起的),特别是当您知道您的代码可以对它们做什么时。仅仅在错误报告中提供更多的细节是一个边缘问题,尽管一些程序的规格可能需要这样做(例如,一个长期运行的服务器,它不应该因为这样的问题而崩溃,而是记录大量的状态信息,给用户一个概要的解释,并且只需要继续工作就可以了。r未来的查询)。
NameErrorTypeErrorKeyErrorValueErrorSyntaxErrorAttributeErrortheindex等等,可以认为是由于程序中的错误--错误,而不是程序员控制之外的问题。如果您正在释放一个库或框架,这样您的代码将被您控制之外的其他代码调用,那么此类错误很可能在其他代码中;您通常应该让异常传播,以帮助其他程序员调试自己的错误。如果您要发布一个应用程序,您就拥有这些bug,并且您必须选择帮助您找到它们的策略。
如果在最终用户运行程序时出现错误,则应记录大量状态信息,并向用户简要解释和道歉(可能是请求向您发送日志信息,如果您无法自动执行此操作,或者至少在发送任何来自用户的机器归您所有)。到目前为止,您可能可以保存一些用户的工作,但通常(在一个已知有问题的程序中)这些工作可能无论如何都不起作用。
当然,大多数错误都应该在您自己的测试过程中出现;在这种情况下,传播异常是有用的,因为您可以将它连接到调试器并研究错误的详细信息。
有时,像这样的异常出现仅仅是因为“请求原谅比请求许可更容易”(EAFP),这是Python中完全可以接受的编程技术。在这种情况下,你当然应该马上处理它们。例如:

try:
return mylist[theindex]
except IndexError:
return None

在这里,您可能期望 mylist通常是 mylist的有效索引,但偶尔会超出 None的界限——而后一种情况,根据此代码段所属的假设应用程序的语义,不是错误,只是考虑到该列表在概念上是可以修复的一点异常情况。在两侧扩展,无限个 KeyErrors。只尝试/排除比正确检查索引的正负值更容易(如果超出界限是一个真正罕见的情况,则更快)。
同样,由于dicts的 AttributeError内置方法和 getattr方法(允许您提供默认值)、 get等,因此 collections.defaultdictIndexError的适当情况发生的频率较低;但是列表没有直接等效的方法,因此,对于 来说,try/except更常见。
试图捕获语法错误、类型错误、值错误、名称错误等,这是一个比较罕见和更具争议性的问题——尽管如果错误是在框架/应用程序试图加载和执行的控件之外的“插件”中诊断出来的,则肯定是适当的。动态地(实际上,在这种情况下,您提供了一个库或类似的库,并且需要与您无法控制的代码和平共存,这很可能是错误的)。类型和值错误有时可能发生在EAFP模式中——例如,当您试图重载一个函数以接受一个字符串或一个数字,并且在每种情况下的行为都略有不同时,捕获这些错误可能比检查类型要好——但是函数的概念因此经常会有人质疑。
回到“用户和环境错误”,用户在给您输入时不可避免地会出错,指出一个实际上不存在的文件名(或者您没有读或写的权限,如果这是您应该做的),等等:所有这些错误当然应该是C。会给用户一个清晰的解释,告诉他们什么地方出了问题,还有一个让输入正确的机会。网络有时会出现故障,数据库或其他外部服务器可能不会像预期的那样响应,等等--有时值得注意这些问题并重试(可能在稍等之后--可能会向用户指示出问题所在,例如,他们可能意外地拔下了一辆出租车你想给他们一个机会去解决问题,告诉你什么时候再试一次),有时候(特别是在无人值守的长时间运行的程序中),除了有序的关机(以及环境中每一个可能相关方面的详细记录),你什么也做不了。
所以,简而言之,你的问题的答案是,“它取决于”;-)。我希望我已经在列出它可以依赖的许多情况和方面,并推荐对这些问题采取最有用的态度。

关于python - 我应该如何正确处理Python3中的异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2913819/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com