python:在 try 语句中崩溃,预期的行为?

python: crash inside try statement, expected behaivour?

我过去遇到过类似的问题,python 代码在 try 语句中崩溃。代码失败,因为它试图打开的文件或目录都不存在。但是因为它在 try 语句中,我不明白为什么代码会中断。

{避免任何 reader 花费太多时间试图理解代码的前提。它正在尝试查找区域文件的顶点,来自;

a) 一个主文件,如果它不存在或者是坏的,试试 (b)

b) 一个特定于它的名字的文件,如果它不存在或者是坏的,执行 (c)

c) 创建一个新的 }

p.s。以下代码不够优雅,可能不是我尝试做的事情的最终解决方案。

    try:
        x1,y1, x2,y2 = np.loadtxt('regions/master.reg')
        plt.plot([x1,x1,x2,x2,x1],[y1,y2,y2,y1,y1], c='k')
        plt.draw()
        if (raw_input('Master Acceptable? (y/n): ') =='n'): raise(NameError)
    except NameError:
        try:
            x1,y1, x2,y2 = np.loadtxt('regions/'+self.name[:-5]+'.reg')
            plt.plot([x1,x1,x2,x2,x1],[y1,y2,y2,y1,y1], c='r')
            plt.draw()
            if raw_input('Reg Acceptable? (y/n): ') =='n': raise(NameError)

        except NameError:
            quality = False
            while not quality:
                x1=int(input('x, top left: '))
                y1=int(input('y, top right: '))
                x2=int(input('x, bottom left: '))
                y2=int(input('y, bottom right: '))
                plt.plot([x1,x1,x2,x2,x1],[y1,y2,y2,y1,y1], c='r')
                plt.draw()
                if raw_input('Acceptable? (y/n): ') =='y': quality=True

和错误(只是说文件不存在)

File "pre_science.py", line 45, in crop
  x1,y1, x2,y2 = np.loadtxt('regions/master.reg')
File "/usr/local/lib/python2.7/dist-packages/numpy/lib/npyio.py", line 917, in loadtxt
  fh = np.lib._datasource.open(fname, 'rt', encoding=encoding)
File "/usr/local/lib/python2.7/dist-packages/numpy/lib/_datasource.py", line 260, in open
  return ds.open(path, mode, encoding=encoding, newline=newline)
File "/usr/local/lib/python2.7/dist-packages/numpy/lib/_datasource.py", line 616, in open
  raise IOError("%s not found." % path)
IOError: regions/master.reg not found.

所以我的问题是,这是预期的行为吗?

您在 try-except 块中指定您期望 NameError,但您得到的是 IOError .

通过使用

try:
    ....
except NameError:
    ....

您只处理 NameError 类型的异常。抛出的所有其他异常(在您的情况下 IOError)不会在任何地方处理,从而使您的代码崩溃。

移除 expect 后的 NameError 或按以下方式添加额外的预期错误

try:
    ....
expect NameError, IOError:
    ....

您正在尝试仅捕获 NameError。使其同时捕获 IOError 和 NameError

try:
    ...
    ...
except (IOError, NameError):
    ...
    ...

NameError是错误的异常类型,使用OSError:

try:
    x1,y1, x2,y2 = np.loadtxt('regions/master.reg')
    plt.plot([x1,x1,x2,x2,x1],[y1,y2,y2,y1,y1], c='k')
    plt.draw()
    if raw_input('Master Acceptable? (y/n): ') =='n': raise OSError()
except OSError:
    try:
        x1,y1, x2,y2 = np.loadtxt('regions/'+self.name[:-5]+'.reg')
        plt.plot([x1,x1,x2,x2,x1],[y1,y2,y2,y1,y1], c='r')
        plt.draw()
        if raw_input('Reg Acceptable? (y/n): ') =='n': raise OSError()
    except OSError:
        while True:
            x1=int(input('x, top left: '))
            y1=int(input('y, top right: '))
            x2=int(input('x, bottom left: '))
            y2=int(input('y, bottom right: '))
            plt.plot([x1,x1,x2,x2,x1],[y1,y2,y2,y1,y1], c='r')
            plt.draw()
            if raw_input('Acceptable? (y/n): ') =='y':
                break

一般来说,NameError 不应用作用户生成的异常,因为 NameError 几乎总是表示编程错误。

本着“不要重复自己”的精神,重组后的代码如下所示:

from functools import partial
from itertools import cycle, chain

def input_rect():
    x1 = int(raw_input('x, top left: '))
    y1 = int(raw_input('y, top right: '))
    x2 = int(raw_input('x, bottom left: '))
    y2 = int(raw_input('y, bottom right: '))

for reader in chain([
        partial(np.loadtxt, 'regions/master.reg'),
        partial(np.loadtxt, 'regions/'+self.name[:-5]+'.reg'),
    ], cycle([input_rect]))
    try:
        x1, y1, x2, y2 = reader()
    except (ValueError, OSError):
        pass
    else:
        plt.plot([x1,x1,x2,x2,x1],[y1,y2,y2,y1,y1], c='r')
        plt.draw()
        if raw_input('Acceptable? (y/n): ') == 'y':
            break