Python尝试其他

try语句的可选else子句的用意是什么?

如果执行落在try的底部, else块中的语句被执行 – 如果没有exception。 老实说,我从来没有find一个需要。

但是, 处理exception注意事项:

else子句的使用要比向try子句中添加额外的代码要好,因为它避免了意外捕获由try … except语句保护的代码没有引发的exception。

所以,如果你有一个方法,例如可以抛出一个IOError ,并且想要捕获它引发的exception,但是如果第一次操作成功,你想做其他事情,而且你不想捕获IOError从这个操作,你可能会写这样的东西:

  try: operation_that_can_throw_ioerror() except IOError: handle_the_exception_somehow() else: # we don't want to catch the IOError if it's raised another_operation_that_can_throw_ioerror() finally: something_we_always_need_to_do() 

如果您在operation_that_can_throw_ioerror之后放置another_operation_that_can_throw_ioerror()except将捕获第二个调用的错误。 如果你把它放在整个try块之后,它会一直运行,直到finallyelse让你确定

  1. 第二个操作只在没有exception的情况下运行,
  2. 它在finally块之前运行,并且
  3. 它引发的任何IOError都不会在这里被捕获

有一个很大的原因使用else风格和可读性。 在处理它们的代码附近保留可能导致exception的代码通常是一个好主意。 例如,比较这些:

 try: from EasyDialogs import AskPassword // 20 other lines getpass = AskPassword except ImportError: getpass = default_getpass 

 try: from EasyDialogs import AskPassword except ImportError: getpass = default_getpass else: // 20 other lines getpass = AskPassword 

第二个好的时候except不能提前回来,或者重新抛出exception。 如果可能的话,我会写:

 try: from EasyDialogs import AskPassword except ImportError: getpass = default_getpass return False // or throw Exception('something more descriptive') // 20 other lines getpass = AskPassword 

注意:从最近发布的复本复制到这里 ,所有这些“AskPassword”的东西。

一个用途:testing一些应该引发exception的代码。

 try: this_should_raise_TypeError() except TypeError: pass except: assert False, "Raised the wrong exception type" else: assert False, "Didn't raise any exception" 

(这个代码应该在实践中抽象成一个更通用的testing。)

Python尝试其他

try语句的可选else子句的用意是什么?

概要

else语句在没有exception的情况下运行,如果没有被returncontinuebreak语句break

其他答案错过了最后一部分。

从文档:

当控制stream出 try子句的末尾时,可选的else子句被执行。*

(Bolding补充说)脚注写道:

*目前,除非出现exception情况或者执行了returncontinuebreak语句,否则控制权“stream失”。

它至less需要一个前面的except子句( 参见语法 )。 所以它不是“尝试 – 其他”,它是“尝试 – 除了别的(最后)”, elsefinally )是可选的。

Python教程阐述了预期的用法:

try … except语句有一个可选的else子句,当存在时,必须遵循除了子句之外的所有子句。 如果try子句不引发exception,则必须执行该代码。 例如:

 for arg in sys.argv[1:]: try: f = open(arg, 'r') except IOError: print 'cannot open', arg else: print arg, 'has', len(f.readlines()), 'lines' f.close() 

else子句的使用要比向try子句中添加额外的代码要好,因为它避免了意外捕获由try … except语句保护的代码没有引发的exception。

区分else与代码块之后的代码示例

如果你处理一个错误, else块将不会运行。 例如:

 def handle_error(): try: raise RuntimeError('oops!') except RuntimeError as error: print('handled a RuntimeError, no big deal.') else: print('if this prints, we had no error!') # won't print! print('And now we have left the try block!') # will print! 

现在,

 >>> handle_error() handled a RuntimeError, no big deal. And now we have left the try block! 

当你清理完成时,我发现它确实很有用,即使有一个例外:

 try: data = something_that_can_go_wrong() except Exception as e: # yes, I know that's a bad way to do it... handle_exception(e) else: do_stuff(data) finally: clean_up() 

即使你现在不能想到它的使用,你可以打赌必须有一个使用它。 这是一个难以想象的样本:

else

 a = [1,2,3] try: something = a[2] except: print "out of bounds" else: print something 

没有else

 try: something = a[2] except: print "out of bounds" if "something" in locals(): print something 

如果没有错误发生,你可以在这里定义somethingvariables。 你可以在try块之外移除它,但是如果定义了一个variables,那么它需要一些杂乱的检测。

来自错误和exception#处理exception – docs.python.org

try ... except语句有一个可选的else子句,当存在时,必须遵循除了子句之外的所有子句。 如果try子句不引发exception,则必须执行该代码。 例如:

 for arg in sys.argv[1:]: try: f = open(arg, 'r') except IOError: print 'cannot open', arg else: print arg, 'has', len(f.readlines()), 'lines' f.close() 

else子句的使用要比向try子句中添加额外的代码要好,因为它避免了意外捕获由try … except语句保护的代码没有引发的exception。

在PEP 380中有一个很好的例子。 基本上,它归结为在algorithm的不同部分做不同的exception处理。

这是这样的:

 try: do_init_stuff() except: handle_init_suff_execption() else: try: do_middle_stuff() except: handle_middle_stuff_exception() 

这使您可以将exception处理代码写入更接近发生exception的位置。

Try-except-else对于将EAFP模式与鸭式打字相结合非常好:

 try: cs = x.cleanupSet except AttributeError: pass else: for v in cs: v.cleanup() 

你可能这个天真的代码是好的:

 try: for v in x.cleanupSet: v.clenaup() except AttributeError: pass 

这是意外隐藏代码中严重错误的好方法。 我错误地清理了那里,但是让我知道的AttributeError正在被吞噬。 更糟糕的是,如果我写的是正确的,但是清理方法偶尔会传入一个用户types,这个用户types有一个错误的属性,导致它默默地中途失败并且保持文件不被closures? 祝你好运,debugging一个。

看看Python的参考 ,似乎还没有例外之后try执行。 如果当控制stream出try子句的末尾,则执行可选的else子句。 2 else子句中的exception不由前面的except子句处理。

潜入Python有一个例子,如果我理解正确,在try块,他们尝试导入一个模块,当失败时,你会得到exception和绑定默认,但是当它的工作,你有一个选项进入else块和绑定什么是必需的(请参阅链接的例子和解释)。

如果你试图在catch块中工作,它可能会抛出另一个exception – 我猜这就是else块的好处了。

而已。 存在try-except子句的“else”块,用于在(且仅当)尝试操作成功时运行的代码。 它可以被使用,并且可以被滥用。

 try: fp= open("configuration_file", "rb") except EnvironmentError: confdata= '' # it's ok if the file can't be opened else: confdata= fp.read() fp.close() # your code continues here # working with (possibly empty) confdata 

就我个人而言,我喜欢它,并在适当的时候使用它。 它在语义上将语句分组。

大多数的答案似乎都集中在为什么我们不能把这些材料放在try子句本身的else子句中。 try语句中的else子句有什么特别的问题,为什么else子句的代码不能 try块本身之后,这个问题被重复到这个问题上,但是我没有看到对这个问题的明确答复这里。 我觉得https://stackoverflow.com/a/3996378/1503120出色地回答了这个问题。; 我也试图阐明在https://stackoverflow.com/a/22579805/1503120各个条款的各种意义。;

也许一个用途可能是:

 #debug = [] def debuglog(text, obj=None): " Simple little logger. " try: debug # does global exist? except NameError: pass # if not, don't even bother displaying except: print('Unknown cause. Debug debuglog().') else: # debug does exist. # Now test if you want to log this debug message # from caller "obj" try: if obj in debug: print(text) # stdout except TypeError: print('The global "debug" flag should be an iterable.') except: print('Unknown cause. Debug debuglog().') def myfunc(): debuglog('Made it to myfunc()', myfunc) debug = [myfunc,] myfunc() 

也许这会导致你太用。

else块通常可以用来补充每个exceptexceptfunction。

 try: test_consistency(valuable_data) except Except1: inconsistency_type = 1 except Except2: inconsistency_type = 2 except: # Something else is wrong raise else: inconsistency_type = 0 """ Process each individual inconsistency down here instead of inside the except blocks. Use 0 to mean no inconsistency. """ 

在这种情况下,除了block以外的每一个都设置了inconsistency_type ,这样在else中的无错情况下行为就被补充了。

当然,我把它描述成一个可能会在你自己的代码中出现的模式。 在这个特定的情况下,你可以在try块之前设置inconsistency_type为0。

在运行数据库查询并将这些查询的结果logging到具有相同风格/types的单独数据库的情况下,我发现try: ... else: construct是有用的。 比方说,我有很多工作线程处理提交给队列的数据库查询

 #in a long running loop try: query = queue.get() conn = connect_to_db(<main db>) curs = conn.cursor() try: curs.execute("<some query on user input that may fail even if sanitized">) except DBError: logconn = connect_to_db(<logging db>) logcurs = logconn.cursor() logcurs.execute("<update in DB log with record of failed query") logcurs.close() logconn.close() else: #we can't put this in main try block because an error connecting #to the logging DB would be indistinguishable from an error in #the mainquery #We can't put this after the whole try: except: finally: block #because then we don't know if the query was successful or not logconn = connect_to_db(<logging db>) logcurs = logconn.cursor() logcurs.execute("<update in DB log with record of successful query") logcurs.close() logconn.close() #do something in response to successful query except DBError: #This DBError is because of a problem with the logging database, but #we can't let that crash the whole thread over what might be a #temporary network glitch finally: curs.close() conn.close() #other cleanup if necessary like telling the queue the task is finished 

当然,如果你能区分可能出现的exception,你不必使用它,但是如果代码对成功的代码作出反应,可能会抛出与成功的exception相同的exception,而且你不能让第二个可能的exception去,或成功立即返回(这将杀死在我的情况下的线程),那么这确实派上用场。

我发现else有用的处理可能不正确的configuration文件:

 try: value, unit = cfg['locks'].split() except ValueError: msg = 'lock must consist of two words separated by white space' self.log('warn', msg) else: # get on with lock processing if config is ok 

该错误是一个温和的(大部分程序仍然有效),处理锁的代码很小。

这里是另一个我喜欢使用这种模式的地方:

  while data in items: try data = json.loads(data) except ValueError as e: log error else: # work on the `data` 

假设你的编程逻辑取决于一个字典是否有一个给定的键入口。 你可以使用if... else...构造来testingdict.get(key)的结果,或者你可以这样做:

 try: val = dic[key] except KeyError: do_some_stuff() else: do_some_stuff_with_val() 

我能想到的其中一种使用场景是不可预知的例外情况,如果您再次尝试,可以避免这种情况。 例如,当try块中的操作涉及随机数时:

 while True: try: r = random.random() some_operation_that_fails_for_specific_r(r) except Exception: continue else: break 

但是,如果可以预测exception,则应该始终在exception之前selectvalidation。 但是,并不是所有的东西都可以预测,所以这个代码模式就有它的地位。

else:块是混乱和(几乎)无用的。 这也是forwhile语句的一部分。

其实,即使是在一个陈述中, else:也可能被真正可怕的方式滥用,造成很难find的错误。

考虑这个。

  if a < 10: # condition stated explicitly elif a > 10 and b < 10: # condition confusing but at least explicit else: # Exactly what is true here? # Can be hard to reason out what condition is true 

别再想else: 。 这通常是一个问题。 除了在if语句中,避免它,甚至考虑loggingelse条件以使其明确。