Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/302.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 除了在每个函数中,我们是否使用try?_Python_Exception - Fatal编程技术网

Python 除了在每个函数中,我们是否使用try?

Python 除了在每个函数中,我们是否使用try?,python,exception,Python,Exception,除了块之外,我们是否应该总是用一个try…来封装我们编写的每个函数? 我这样问是因为有时在一个函数中我们会引发异常,而调用此函数的调用方没有异常 def caller(): stdout, stderr = callee(....) def callee(): .... if stderr: raise StandardError(....) 然后我们的应用程序崩溃了。在这种明显的情况下,我试图用try..except将被调用者和调用者括起来 但是我已经读

除了块之外,我们是否应该总是用一个
try…来封装我们编写的每个函数?
我这样问是因为有时在一个函数中我们会引发异常,而调用此函数的调用方没有异常

def caller():
   stdout, stderr = callee(....)


def callee():
   ....
    if stderr:
       raise StandardError(....)
然后我们的应用程序崩溃了。在这种明显的情况下,我试图用
try..except
将被调用者和调用者括起来

但是我已经读了很多Python代码,他们不会一直做这些
try..block


真正困扰我的是:


如果有第三个函数在其中一个语句中调用
addandremove()
,我们是否也会在调用的周围加上try..except块?如果第三个函数有3行,并且每个函数调用本身都有一个try-except,该怎么办?我很抱歉把这件事搞砸了。但这是我没有遇到的问题。

您应该使用try-catch块,以便能够专门定位异常的源。你可以把这些块放在你想要的任何东西周围,但是除非它们产生某种有用的信息,否则就没有必要添加它们。

试试看
/
,除非
子句只有在你知道如何处理引发的错误时才真正有用。采取以下方案:

while True:
    n=raw_input("Input a number>")
    try:
       n=float(n)
       break
    except ValueError:
       print ("That wasn't a number!")  #Try again.
但是,您可能具有以下功能:

def mult_2_numbers(x,y):
    return x*y
用户可以尝试将其用作:

my_new_list=mult_2_numbers([7,3],[8,7])

用户可以将其放入try/except块,但是
我的新列表
将不会被定义,并且可能只是在稍后引发异常(可能是名称错误)。在这种情况下,您将更难调试,因为回溯中的行号/信息指向一段不是真正问题的代码;主要例外情况的作用包括(引自《辉煌之书》):

  • 错误处理
  • 事件通知
  • 特殊案件处理
  • 终止行动
  • 异常控制流

当您知道将出现什么错误时,使用try/except进行调试。否则,您不必对每个函数都使用try/except

例外,顾名思义,是指特殊情况——不应该发生的事情

…因为它们可能不应该发生,在大多数情况下,你可以忽略它们。这是一件好事

有时您会执行以下操作,但特定的例外情况除外,例如,如果我执行以下操作:

urllib2.urlopen("http://example.com")
在这种情况下,可以预期“无法联系服务器”错误,因此您可以执行以下操作:

try:
    urllib2.urlopen("http://example.com")
except urllib2.URLError:
    # code to handle the error, maybe retry the server,
    # report the error in a helpful way to the user etc
import mystuff

mystuff.addandremove("myfile.txt")
然而,试图抓住每一个可能的错误是徒劳的——有无数的事情可能会出错。。作为一个奇怪的例子,如果一个模块修改了
urllib2
并删除了
urlopen
属性,那么会发生什么呢?没有合理的理由期待
namererror
,也没有合理的方法可以处理这样的错误,因此您只能让异常传播

让您的代码带着回溯退出是一件好事-它使您能够轻松地看到问题的起因,以及导致问题的原因(基于异常及其消息),并修复问题的原因,或者在正确的位置处理异常

简言之,只有当您可以对异常做一些有用的事情时,才可以处理异常。否则,试图处理所有无数可能的错误只会使您的代码更混乱,更难修复


在您提供的示例中,try/except块什么都不做——它们只是重新引发异常,因此它与更整洁的:

def cmd(cmdl):
    pid = Popen(cmdl, stdout=PIPE, stderr=PIPE)
    stdout, stderr = pid.communicate()
    if pid.returncode != 0:
        raise StandardError(stderr)
    return (stdout, stderr)

# Note: Better to use actual args instead of * and **,
# gives better error handling and docs from help()
def addandremove(fname, local = None, vcs = 'hg'):
    if target is None:
       target = os.getcwd() 

    if vcs is "hg":
        stdout, stderr = cmd(['hg', 'addremove', '--similarity 95'])
    return True
与异常处理相关的唯一一件事是,如果找不到“hg”命令,那么所产生的异常并不是特别描述性的。所以对于图书馆,我会做一些类似的事情:

class CommandNotFound(Exception): pass

def cmd(cmdl):
    try:
        pid = Popen(cmdl, stdout=PIPE, stderr=PIPE)
    except OSError, e:
        if e.errno == 2:
            raise CommandNotFound("The command %r could not be found" % cmdl)
        else:
            # Unexpected error-number in OSError,
            # so a bare "raise" statement will reraise the error
            raise

    stdout, stderr = pid.communicate()
    if pid.returncode != 0:
        raise StandardError(stderr)
    return (stdout, stderr)
这只是在更清晰的“CommandNotFound”中封装了可能令人困惑的“OSError”异常

重读这个问题,我怀疑您可能误解了Python异常是如何工作的(“调用此函数的调用方没有异常”位,希望澄清一下:

调用方函数不需要了解可能从子函数引发的异常。您只需调用
cmd()
函数,希望它能正常工作

假设您的代码位于
mystuff
模块中,而其他人想要使用它,他们可能会这样做:

try:
    urllib2.urlopen("http://example.com")
except urllib2.URLError:
    # code to handle the error, maybe retry the server,
    # report the error in a helpful way to the user etc
import mystuff

mystuff.addandremove("myfile.txt")
或者,如果用户没有安装
hg
,他们可能希望给出一条漂亮的错误消息并退出:

import mystuff

try:
    mystuff.addandremove("myfile.txt")
except mystuff.CommandNotFound:
    print "You don't appear to have the 'hg' command installed"
    print "You can install it with by... etc..."
    myprogram.quit("blahblahblah")

关于内省类型工具和“异常”处理,您的编码团队需要做出几个编程决策

使用异常处理的一个好地方是操作系统调用,例如文件操作。推理是,例如,一个文件的访问可能会受到限制,无法被客户端应用程序访问。该访问限制通常是操作系统管理任务,而不是Python应用程序函数。因此,在应用程序没有控制权

您可以将上一段中异常的应用范围进行更广泛的修改,即将异常用于团队代码无法控制的事情,例如所有“设备”或操作系统资源,如操作系统计时器、符号链接、网络连接等

另一种常见的使用情况是,当您使用一个库或包,该库或包被设计为通过大量异常,并且该包希望您捕获或编码这些异常。一些包被设计为抛出尽可能少的异常,并希望您根据返回值进行编码。那么您的异常应该很少

一些编码团队使用异常作为记录应用程序中“事件”的一种方式

我发现,在决定是否使用异常时,我要么通过不使用大量try/except来编程以最小化失败,要么让调用例程期望有效的返回值,要么期望无效的返回值