在python中应该多久定义一次自定义异常?

在python中应该多久定义一次自定义异常?,python,Python,在我为监视一些专门的工作流而编写的python模块中,为了消除潜在的竞争条件,我学习了python的“请求原谅比许可更容易”(EAFP)编码风格,现在我使用try/except块提出了许多自定义异常,我过去使用if/thens 我是python新手,这种EAFP风格在逻辑上是有意义的,似乎使我的代码更加健壮,但这方面的一些东西感觉太过火了。在每个方法中定义一个或多个异常是错误的做法吗 这些自定义异常往往只对单个方法有用,虽然它看起来像是功能正确的解决方案,但似乎需要维护很多代码 下面是一个示例方

在我为监视一些专门的工作流而编写的python模块中,为了消除潜在的竞争条件,我学习了python的“请求原谅比许可更容易”(EAFP)编码风格,现在我使用try/except块提出了许多自定义异常,我过去使用if/thens

我是python新手,这种EAFP风格在逻辑上是有意义的,似乎使我的代码更加健壮,但这方面的一些东西感觉太过火了。在每个方法中定义一个或多个异常是错误的做法吗

这些自定义异常往往只对单个方法有用,虽然它看起来像是功能正确的解决方案,但似乎需要维护很多代码

下面是一个示例方法,例如:

class UploadTimeoutFileMissing(Exception):
    def __init__(self, value):
        self.parameter = value
    def __str__(self):
        return repr(self.parameter)

class UploadTimeoutTooSlow(Exception):
    def __init__(self, value):
        self.parameter = value
    def __str__(self):
        return repr(self.parameter)

def check_upload(file, timeout_seconds, max_age_seconds, min_age_seconds):

    timeout = time.time() + timeout_seconds

    ## Check until file found or timeout
    while (time.time() < timeout):

        time.sleep(5)
        try:
            filetime = os.path.getmtime(file)
            filesize = os.path.getsize(file)
        except OSError:
            print "File not found %s" % file
            continue

        fileage = time.time() - filetime

        ## Make sure file isn't pre-existing
        if fileage > max_age_seconds:
            print "File too old %s" % file
            continue

        ## Make sure file isn't still uploading
        elif fileage <= min_age_seconds:
            print "File too new %s" % file
            continue

        return(filetime, filesize)

    ## Timeout
    try:
        filetime
        filesize
        raise UploadTimeoutTooSlow("File still uploading")

    except NameError:
        raise UploadTimeoutFileMissing("File not sent")
类UploadTimeoutFileMissing(异常):
定义初始值(自身,值):
self.parameter=值
定义(自我):
返回报告(自身参数)
类UploadTimeoutTooSlow(异常):
定义初始值(自身,值):
self.parameter=值
定义(自我):
返回报告(自身参数)
def检查上传(文件、超时秒、最长时间秒、最短时间秒):
超时=时间。时间()+超时\u秒
##检查直到找到文件或超时
while(time.time()<超时):
时间。睡眠(5)
尝试:
filetime=os.path.getmtime(文件)
filesize=os.path.getsize(文件)
除操作错误外:
打印“未找到文件%s”%s文件
持续
fileage=time.time()-filetime
##确保文件不是预先存在的
如果文件老化>最大老化秒数:
打印“文件太旧%s”%s文件
持续
##确保文件未仍在上载
elif文件
在每个方法中定义一个或多个异常是错误的做法吗

每个模块一个更为典型。当然,这取决于详细的语义。问题归结为:“你到底想抓什么?”

如果您永远不会在代码中使用
,除了这个verydeailedexception:
,那么您非常详细的异常就没有多大帮助

如果你能做到这一点:
除了错误作为e:If e.some_special_case
对于极少数重要的情况,那么你可以很容易地简化为每个模块一个异常,并将你的特殊情况作为异常的属性来处理,而不是不同类型的异常

常见的建议(每个模块一个,名为
Error
)意味着您的代码通常如下所示

try: 
    something
except some_module.Error as e:
    carry on
这为您提供了一个很好的命名约定:
module.Error
。这涵盖了许多罪恶


另一方面,如果你认为你有“潜在的竞争条件”,你可能应该正确地重新设计,或者停止尝试使用线程,或者切换到多处理。如果你使用多重处理,你会发现很容易避免竞争条件

为每个方法定义一个或多个异常

如果您的意思是,异常实际上是按照“在方法体中”中的方法定义的,那么yes。这是个坏习惯。如果您定义了两个与同一错误相关的异常,但创建了两个异常,因为两个不同的方法引发了它们,则也是如此

如果您询问对每个方法提出一个以上的异常是否是不好的做法,那么,这就是好的做法。如果错误不属于同一类别,则可以为每个模块定义几个异常


通常,对于较大的模块,您将定义多个异常。如果您要处理某个算术库,并定义一个ZeroDivisionError和OverflowerError(如果它们还没有在python中定义,因为您当然可以重用它们),那将非常好。

我认为没有必要为每种可能的场景都定义一个非常特定的异常。一个
UploadTimeoutError
就可以了,您可以自定义异常字符串——毕竟,这就是字符串的用途。请注意,python并没有为每种可能的语法错误类型单独设置异常,只是一个常规的
SyntaxError

另外-是否确实有必要为每个自定义异常定义
\uuuuu init\uuuu
\uuuu str\uuuu
方法?据我所知,如果没有实现任何异常行为,则不需要添加任何代码:

>>> class MyException(Exception): pass
... 
>>> raise MyException("oops!")
Traceback (most recent call last):
  File "<ipython console>", line 1, in <module>
MyException: oops!    
>>> str(MyException("oops!"))
'oops!'
>>类MyException(异常):通过
... 
>>>引发MyException(“oops!”)
回溯(最近一次呼叫最后一次):
文件“”,第1行,在
我的例外:哎呀!
>>>str(MyException(“oops!”)
“哎呀!”

我将对此进行权衡,因为自定义异常对我来说非常重要。我会解释我的情况,读者可以根据自己的情况来权衡

我是一家视觉效果公司的管道架构师-我所做的大部分工作都涉及到开发我称之为“Facility API”的东西-这是一个由大量模块组成的系统,可以处理从文件系统上的定位、管理模块/工具/项目配置到,处理来自各种CG应用程序的数据类型以实现协作

我竭尽全力确保Python的内置异常永远不会出现。由于我们的开发人员将依赖现有模块的生态系统来构建他们自己的工具,因此让API允许泛型
IOError
转义是适得其反的——特别是因为调用例程可能甚至不知道它正在读取文件系统(抽象是一件美妙的事情)。如果底层模块无法表达有关该错误的有意义的信息,则需要做更多的工作

我解决这个问题的方法是创建一个facility exception类,从中派生所有其他facility异常。对于特定类型的任务或特定的主机ap,有其子类