# SOME DESCRIPTIVE TITLE. # Copyright (C) 2001-2025, Python Software Foundation # This file is distributed under the same license as the Python package. # FIRST AUTHOR , YEAR. # # Translators: # Rafael Fontenelle , 2025 # #, fuzzy msgid "" msgstr "" "Project-Id-Version: Python 3.12\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2025-07-25 16:03+0000\n" "PO-Revision-Date: 2025-07-18 19:59+0000\n" "Last-Translator: Rafael Fontenelle , 2025\n" "Language-Team: Chinese (China) (https://app.transifex.com/python-doc/teams/5390/zh_CN/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: zh_CN\n" "Plural-Forms: nplurals=1; plural=0;\n" #: ../../tutorial/errors.rst:5 msgid "Errors and Exceptions" msgstr "错误和异常" #: ../../tutorial/errors.rst:7 msgid "" "Until now error messages haven't been more than mentioned, but if you have " "tried out the examples you have probably seen some. There are (at least) " "two distinguishable kinds of errors: *syntax errors* and *exceptions*." msgstr "" "至此,本教程还未深入介绍错误信息,但如果您尝试过本教程前文中的例子,应该已经看到过一些错误信息。错误可(至少)被分为两种:*语法错误* 和 *异常*。" #: ../../tutorial/errors.rst:15 msgid "Syntax Errors" msgstr "语法错误" #: ../../tutorial/errors.rst:17 msgid "" "Syntax errors, also known as parsing errors, are perhaps the most common " "kind of complaint you get while you are still learning Python::" msgstr "语法错误又称解析错误,是学习 Python 时最常见的错误:" #: ../../tutorial/errors.rst:20 msgid "" ">>> while True print('Hello world')\n" " File \"\", line 1\n" " while True print('Hello world')\n" " ^^^^^\n" "SyntaxError: invalid syntax" msgstr "" ">>> while True print('Hello world')\n" " File \"\", line 1\n" " while True print('Hello world')\n" " ^^^^^\n" "SyntaxError: invalid syntax" #: ../../tutorial/errors.rst:26 msgid "" "The parser repeats the offending line and displays little arrows pointing at" " the place where the error was detected. Note that this is not always the " "place that needs to be fixed. In the example, the error is detected at the " "function :func:`print`, since a colon (``':'``) is missing just before it." msgstr "" "解析器会重复出错的行并显示指向检测到错误的位置的小箭头。 请注意这并不一定是需要被修复的位置。 在这个例子中,错误在 :func:`print` " "上被检测到,原因则是在它之前缺少一个冒号 (``':'``)。" #: ../../tutorial/errors.rst:31 msgid "" "The file name (```` in our example) and line number are printed so " "you know where to look in case the input came from a file." msgstr "将会打印文件名 (在我们的例子中为 ````) 和行号以便你在输入是来自文件时能知道要去哪里查看。" #: ../../tutorial/errors.rst:38 msgid "Exceptions" msgstr "异常" #: ../../tutorial/errors.rst:40 msgid "" "Even if a statement or expression is syntactically correct, it may cause an " "error when an attempt is made to execute it. Errors detected during " "execution are called *exceptions* and are not unconditionally fatal: you " "will soon learn how to handle them in Python programs. Most exceptions are " "not handled by programs, however, and result in error messages as shown " "here::" msgstr "" "即使语句或表达式使用了正确的语法,执行时仍可能触发错误。执行时检测到的错误称为 *异常*,异常不一定导致严重的后果:很快我们就能学会如何处理 " "Python 的异常。大多数异常不会被程序处理,而是显示下列错误信息:" #: ../../tutorial/errors.rst:46 msgid "" ">>> 10 * (1/0)\n" "Traceback (most recent call last):\n" " File \"\", line 1, in \n" "ZeroDivisionError: division by zero\n" ">>> 4 + spam*3\n" "Traceback (most recent call last):\n" " File \"\", line 1, in \n" "NameError: name 'spam' is not defined\n" ">>> '2' + 2\n" "Traceback (most recent call last):\n" " File \"\", line 1, in \n" "TypeError: can only concatenate str (not \"int\") to str" msgstr "" ">>> 10 * (1/0)\n" "Traceback (most recent call last):\n" " File \"\", line 1, in \n" "ZeroDivisionError: division by zero\n" ">>> 4 + spam*3\n" "Traceback (most recent call last):\n" " File \"\", line 1, in \n" "NameError: name 'spam' is not defined\n" ">>> '2' + 2\n" "Traceback (most recent call last):\n" " File \"\", line 1, in \n" "TypeError: can only concatenate str (not \"int\") to str" #: ../../tutorial/errors.rst:59 msgid "" "The last line of the error message indicates what happened. Exceptions come " "in different types, and the type is printed as part of the message: the " "types in the example are :exc:`ZeroDivisionError`, :exc:`NameError` and " ":exc:`TypeError`. The string printed as the exception type is the name of " "the built-in exception that occurred. This is true for all built-in " "exceptions, but need not be true for user-defined exceptions (although it is" " a useful convention). Standard exception names are built-in identifiers " "(not reserved keywords)." msgstr "" "错误信息的最后一行说明程序遇到了什么类型的错误。异常有不同的类型,而类型名称会作为错误信息的一部分中打印出来:上述示例中的异常类型依次是::exc:`ZeroDivisionError`," " :exc:`NameError` 和 " ":exc:`TypeError`。作为异常类型打印的字符串是发生的内置异常的名称。对于所有内置异常都是如此,但对于用户定义的异常则不一定如此(虽然这种规范很有用)。标准的异常类型是内置的标识符(不是保留关键字)。" #: ../../tutorial/errors.rst:67 msgid "" "The rest of the line provides detail based on the type of exception and what" " caused it." msgstr "此行其余部分根据异常类型,结合出错原因,说明错误细节。" #: ../../tutorial/errors.rst:70 msgid "" "The preceding part of the error message shows the context where the " "exception occurred, in the form of a stack traceback. In general it contains" " a stack traceback listing source lines; however, it will not display lines " "read from standard input." msgstr "错误信息开头用堆栈回溯形式展示发生异常的语境。一般会列出源代码行的堆栈回溯;但不会显示从标准输入读取的行。" #: ../../tutorial/errors.rst:75 msgid "" ":ref:`bltin-exceptions` lists the built-in exceptions and their meanings." msgstr ":ref:`bltin-exceptions` 列出了内置异常及其含义。" #: ../../tutorial/errors.rst:81 msgid "Handling Exceptions" msgstr "异常的处理" #: ../../tutorial/errors.rst:83 msgid "" "It is possible to write programs that handle selected exceptions. Look at " "the following example, which asks the user for input until a valid integer " "has been entered, but allows the user to interrupt the program (using " ":kbd:`Control-C` or whatever the operating system supports); note that a " "user-generated interruption is signalled by raising the " ":exc:`KeyboardInterrupt` exception. ::" msgstr "" "可以编写程序处理选定的异常。下例会要求用户一直输入内容,直到输入有效的整数,但允许用户中断程序(使用 :kbd:`Control-C` " "或操作系统支持的其他操作);注意,用户中断程序会触发 :exc:`KeyboardInterrupt` 异常。" #: ../../tutorial/errors.rst:89 msgid "" ">>> while True:\n" "... try:\n" "... x = int(input(\"Please enter a number: \"))\n" "... break\n" "... except ValueError:\n" "... print(\"Oops! That was no valid number. Try again...\")\n" "..." msgstr "" ">>> while True:\n" "... try:\n" "... x = int(input(\"Please enter a number: \"))\n" "... break\n" "... except ValueError:\n" "... print(\"Oops! That was no valid number. Try again...\")\n" "..." #: ../../tutorial/errors.rst:97 msgid "The :keyword:`try` statement works as follows." msgstr ":keyword:`try` 语句的工作原理如下:" #: ../../tutorial/errors.rst:99 msgid "" "First, the *try clause* (the statement(s) between the :keyword:`try` and " ":keyword:`except` keywords) is executed." msgstr "首先,执行 *try 子句* (:keyword:`try` 和 :keyword:`except` 关键字之间的(多行)语句)。" #: ../../tutorial/errors.rst:102 msgid "" "If no exception occurs, the *except clause* is skipped and execution of the " ":keyword:`try` statement is finished." msgstr "如果没有触发异常,则跳过 *except 子句*,:keyword:`try` 语句执行完毕。" #: ../../tutorial/errors.rst:105 msgid "" "If an exception occurs during execution of the :keyword:`try` clause, the " "rest of the clause is skipped. Then, if its type matches the exception " "named after the :keyword:`except` keyword, the *except clause* is executed, " "and then execution continues after the try/except block." msgstr "" "如果在执行 :keyword:`try` 子句时发生了异常,则跳过该子句中剩下的部分。 如果异常的类型与 :keyword:`except` " "关键字后指定的异常相匹配,则会执行 *except 子句*,然后跳到 try/except 代码块之后继续执行。" #: ../../tutorial/errors.rst:110 msgid "" "If an exception occurs which does not match the exception named in the " "*except clause*, it is passed on to outer :keyword:`try` statements; if no " "handler is found, it is an *unhandled exception* and execution stops with an" " error message." msgstr "" "如果发生的异常与 *except 子句* 中指定的异常不匹配,则它会被传递到外层的 :keyword:`try` 语句中;如果没有找到处理器,则它是一个" " *未处理异常* 且执行将停止并输出一条错误消息。" #: ../../tutorial/errors.rst:114 msgid "" "A :keyword:`try` statement may have more than one *except clause*, to " "specify handlers for different exceptions. At most one handler will be " "executed. Handlers only handle exceptions that occur in the corresponding " "*try clause*, not in other handlers of the same :keyword:`!try` statement. " "An *except clause* may name multiple exceptions as a parenthesized tuple, " "for example::" msgstr "" ":keyword:`try` 语句可以有多个 *except 子句* 来为不同的异常指定处理程序。 但最多只有一个处理程序会被执行。 " "处理程序只处理对应的 *try 子句* 中发生的异常,而不处理同一 :keyword:`!try` 语句内其他处理程序中的异常。 *except 子句*" " 可以用带圆括号的元组来指定多个异常,例如::" #: ../../tutorial/errors.rst:120 msgid "" "... except (RuntimeError, TypeError, NameError):\n" "... pass" msgstr "" "... except (RuntimeError, TypeError, NameError):\n" "... pass" #: ../../tutorial/errors.rst:123 msgid "" "A class in an :keyword:`except` clause matches exceptions which are " "instances of the class itself or one of its derived classes (but not the " "other way around --- an *except clause* listing a derived class does not " "match instances of its base classes). For example, the following code will " "print B, C, D in that order::" msgstr "" "一个 :keyword:`except` 子句中的类匹配的异常将是该类本身的实例或其所派生的类的实例(但反过来则不可以 --- 列出派生类的 " "*except 子句* 不会匹配其基类的实例)。 例如,下面的代码将依次打印 B, C, D::" #: ../../tutorial/errors.rst:128 msgid "" "class B(Exception):\n" " pass\n" "\n" "class C(B):\n" " pass\n" "\n" "class D(C):\n" " pass\n" "\n" "for cls in [B, C, D]:\n" " try:\n" " raise cls()\n" " except D:\n" " print(\"D\")\n" " except C:\n" " print(\"C\")\n" " except B:\n" " print(\"B\")" msgstr "" "class B(Exception):\n" " pass\n" "\n" "class C(B):\n" " pass\n" "\n" "class D(C):\n" " pass\n" "\n" "for cls in [B, C, D]:\n" " try:\n" " raise cls()\n" " except D:\n" " print(\"D\")\n" " except C:\n" " print(\"C\")\n" " except B:\n" " print(\"B\")" #: ../../tutorial/errors.rst:147 msgid "" "Note that if the *except clauses* were reversed (with ``except B`` first), " "it would have printed B, B, B --- the first matching *except clause* is " "triggered." msgstr "" "请注意如果颠倒 *except 子句* 的顺序(把 ``except B`` 放在最前),则会输出 B, B, B --- 即触发了第一个匹配的 " "*except 子句*。" #: ../../tutorial/errors.rst:150 msgid "" "When an exception occurs, it may have associated values, also known as the " "exception's *arguments*. The presence and types of the arguments depend on " "the exception type." msgstr "发生异常时,它可能具有关联值,即异常 *参数* 。是否需要参数,以及参数的类型取决于异常的类型。" #: ../../tutorial/errors.rst:154 msgid "" "The *except clause* may specify a variable after the exception name. The " "variable is bound to the exception instance which typically has an ``args`` " "attribute that stores the arguments. For convenience, builtin exception " "types define :meth:`~object.__str__` to print all the arguments without " "explicitly accessing ``.args``. ::" msgstr "" "*except 子句* 可能会在异常名称后面指定一个变量。 这个变量将被绑定到异常实例,该实例通常会有一个存储参数的 ``args`` 属性。 " "为了方便起见,内置异常类型定义了 :meth:`~object.__str__` 来打印所有参数而不必显式地访问 ``.args``。 ::" #: ../../tutorial/errors.rst:160 msgid "" ">>> try:\n" "... raise Exception('spam', 'eggs')\n" "... except Exception as inst:\n" "... print(type(inst)) # the exception type\n" "... print(inst.args) # arguments stored in .args\n" "... print(inst) # __str__ allows args to be printed directly,\n" "... # but may be overridden in exception subclasses\n" "... x, y = inst.args # unpack args\n" "... print('x =', x)\n" "... print('y =', y)\n" "...\n" "\n" "('spam', 'eggs')\n" "('spam', 'eggs')\n" "x = spam\n" "y = eggs" msgstr "" ">>> try:\n" "... raise Exception('spam', 'eggs')\n" "... except Exception as inst:\n" "... print(type(inst)) # 异常的类型\n" "... print(inst.args) # 参数保存在 .args 中\n" "... print(inst) # __str__ 允许 args 被直接打印,\n" "... # 但可能在异常子类中被覆盖\n" "... x, y = inst.args # 解包 args\n" "... print('x =', x)\n" "... print('y =', y)\n" "...\n" "\n" "('spam', 'eggs')\n" "('spam', 'eggs')\n" "x = spam\n" "y = eggs" #: ../../tutorial/errors.rst:177 msgid "" "The exception's :meth:`~object.__str__` output is printed as the last part " "('detail') of the message for unhandled exceptions." msgstr "未处理异常的 :meth:`~object.__str__` 输出会被打印为该异常消息的最后部分 ('detail')。" #: ../../tutorial/errors.rst:180 msgid "" ":exc:`BaseException` is the common base class of all exceptions. One of its " "subclasses, :exc:`Exception`, is the base class of all the non-fatal " "exceptions. Exceptions which are not subclasses of :exc:`Exception` are not " "typically handled, because they are used to indicate that the program should" " terminate. They include :exc:`SystemExit` which is raised by " ":meth:`sys.exit` and :exc:`KeyboardInterrupt` which is raised when a user " "wishes to interrupt the program." msgstr "" ":exc:`BaseException` 是所有异常的共同基类。它的一个子类, :exc:`Exception` ,是所有非致命异常的基类。不是 " ":exc:`Exception` 的子类的异常通常不被处理,因为它们被用来指示程序应该终止。它们包括由 :meth:`sys.exit` 引发的 " ":exc:`SystemExit` ,以及当用户希望中断程序时引发的 :exc:`KeyboardInterrupt` 。" #: ../../tutorial/errors.rst:188 msgid "" ":exc:`Exception` can be used as a wildcard that catches (almost) everything." " However, it is good practice to be as specific as possible with the types " "of exceptions that we intend to handle, and to allow any unexpected " "exceptions to propagate on." msgstr "" ":exc:`Exception` " "可以被用作通配符,捕获(几乎)一切。然而,好的做法是,尽可能具体地说明我们打算处理的异常类型,并允许任何意外的异常传播下去。" #: ../../tutorial/errors.rst:193 msgid "" "The most common pattern for handling :exc:`Exception` is to print or log the" " exception and then re-raise it (allowing a caller to handle the exception " "as well)::" msgstr "处理 :exc:`Exception` 最常见的模式是打印或记录异常,然后重新提出(允许调用者也处理异常)::" #: ../../tutorial/errors.rst:197 msgid "" "import sys\n" "\n" "try:\n" " f = open('myfile.txt')\n" " s = f.readline()\n" " i = int(s.strip())\n" "except OSError as err:\n" " print(\"OS error:\", err)\n" "except ValueError:\n" " print(\"Could not convert data to an integer.\")\n" "except Exception as err:\n" " print(f\"Unexpected {err=}, {type(err)=}\")\n" " raise" msgstr "" "import sys\n" "\n" "try:\n" " f = open('myfile.txt')\n" " s = f.readline()\n" " i = int(s.strip())\n" "except OSError as err:\n" " print(\"OS error:\", err)\n" "except ValueError:\n" " print(\"Could not convert data to an integer.\")\n" "except Exception as err:\n" " print(f\"Unexpected {err=}, {type(err)=}\")\n" " raise" #: ../../tutorial/errors.rst:211 msgid "" "The :keyword:`try` ... :keyword:`except` statement has an optional *else " "clause*, which, when present, must follow all *except clauses*. It is " "useful for code that must be executed if the *try clause* does not raise an " "exception. For example::" msgstr "" ":keyword:`try` ... :keyword:`except` 语句具有可选的 *else 子句*,该子句如果存在,它必须放在所有 " "*except 子句* 之后。 它适用于 *try 子句* 没有引发异常但又必须要执行的代码。 例如::" #: ../../tutorial/errors.rst:216 msgid "" "for arg in sys.argv[1:]:\n" " try:\n" " f = open(arg, 'r')\n" " except OSError:\n" " print('cannot open', arg)\n" " else:\n" " print(arg, 'has', len(f.readlines()), 'lines')\n" " f.close()" msgstr "" "for arg in sys.argv[1:]:\n" " try:\n" " f = open(arg, 'r')\n" " except OSError:\n" " print('cannot open', arg)\n" " else:\n" " print(arg, 'has', len(f.readlines()), 'lines')\n" " f.close()" #: ../../tutorial/errors.rst:225 msgid "" "The use of the :keyword:`!else` clause is better than adding additional code" " to the :keyword:`try` clause because it avoids accidentally catching an " "exception that wasn't raised by the code being protected by the " ":keyword:`!try` ... :keyword:`!except` statement." msgstr "" "使用 :keyword:`!else` 子句比向 :keyword:`try` 子句添加额外的代码要好,可以避免意外捕获非 " ":keyword:`!try` ... :keyword:`!except` 语句保护的代码触发的异常。" #: ../../tutorial/errors.rst:230 msgid "" "Exception handlers do not handle only exceptions that occur immediately in " "the *try clause*, but also those that occur inside functions that are called" " (even indirectly) in the *try clause*. For example::" msgstr "异常处理程序不仅会处理在 *try 子句* 中立刻发生的异常,还会处理在 *try 子句* 中调用(包括间接调用)的函数。 例如::" #: ../../tutorial/errors.rst:234 msgid "" ">>> def this_fails():\n" "... x = 1/0\n" "...\n" ">>> try:\n" "... this_fails()\n" "... except ZeroDivisionError as err:\n" "... print('Handling run-time error:', err)\n" "...\n" "Handling run-time error: division by zero" msgstr "" ">>> def this_fails():\n" "... x = 1/0\n" "...\n" ">>> try:\n" "... this_fails()\n" "... except ZeroDivisionError as err:\n" "... print('Handling run-time error:', err)\n" "...\n" "Handling run-time error: division by zero" #: ../../tutorial/errors.rst:248 msgid "Raising Exceptions" msgstr "触发异常" #: ../../tutorial/errors.rst:250 msgid "" "The :keyword:`raise` statement allows the programmer to force a specified " "exception to occur. For example::" msgstr ":keyword:`raise` 语句支持强制触发指定的异常。例如:" #: ../../tutorial/errors.rst:253 msgid "" ">>> raise NameError('HiThere')\n" "Traceback (most recent call last):\n" " File \"\", line 1, in \n" "NameError: HiThere" msgstr "" #: ../../tutorial/errors.rst:258 msgid "" "The sole argument to :keyword:`raise` indicates the exception to be raised. " "This must be either an exception instance or an exception class (a class " "that derives from :class:`BaseException`, such as :exc:`Exception` or one of" " its subclasses). If an exception class is passed, it will be implicitly " "instantiated by calling its constructor with no arguments::" msgstr "" ":keyword:`raise` 唯一的参数就是要触发的异常。这个参数必须是异常实例或异常类(派生自 :class:`BaseException` " "类,例如 :exc:`Exception` 或其子类)。如果传递的是异常类,将通过调用没有参数的构造函数来隐式实例化:" #: ../../tutorial/errors.rst:264 msgid "raise ValueError # shorthand for 'raise ValueError()'" msgstr "raise ValueError # 'raise ValueError()' 的简化" #: ../../tutorial/errors.rst:266 msgid "" "If you need to determine whether an exception was raised but don't intend to" " handle it, a simpler form of the :keyword:`raise` statement allows you to " "re-raise the exception::" msgstr "如果只想判断是否触发了异常,但并不打算处理该异常,则可以使用更简单的 :keyword:`raise` 语句重新触发异常:" #: ../../tutorial/errors.rst:270 msgid "" ">>> try:\n" "... raise NameError('HiThere')\n" "... except NameError:\n" "... print('An exception flew by!')\n" "... raise\n" "...\n" "An exception flew by!\n" "Traceback (most recent call last):\n" " File \"\", line 2, in \n" "NameError: HiThere" msgstr "" #: ../../tutorial/errors.rst:285 msgid "Exception Chaining" msgstr "异常链" #: ../../tutorial/errors.rst:287 msgid "" "If an unhandled exception occurs inside an :keyword:`except` section, it " "will have the exception being handled attached to it and included in the " "error message::" msgstr "如果一个未处理的异常发生在 :keyword:`except` 部分内,它将会有被处理的异常附加到它上面,并包括在错误信息中::" #: ../../tutorial/errors.rst:291 msgid "" ">>> try:\n" "... open(\"database.sqlite\")\n" "... except OSError:\n" "... raise RuntimeError(\"unable to handle error\")\n" "...\n" "Traceback (most recent call last):\n" " File \"\", line 2, in \n" "FileNotFoundError: [Errno 2] No such file or directory: 'database.sqlite'\n" "\n" "During handling of the above exception, another exception occurred:\n" "\n" "Traceback (most recent call last):\n" " File \"\", line 4, in \n" "RuntimeError: unable to handle error" msgstr "" #: ../../tutorial/errors.rst:306 msgid "" "To indicate that an exception is a direct consequence of another, the " ":keyword:`raise` statement allows an optional :keyword:`from` " "clause::" msgstr "" "为了表明一个异常是另一个异常的直接后果, :keyword:`raise` 语句允许一个可选的 :keyword:`from` 子句::" #: ../../tutorial/errors.rst:309 msgid "" "# exc must be exception instance or None.\n" "raise RuntimeError from exc" msgstr "" "# exc 必须为异常实例或为 None。\n" "raise RuntimeError from exc" #: ../../tutorial/errors.rst:312 msgid "This can be useful when you are transforming exceptions. For example::" msgstr "转换异常时,这种方式很有用。例如:" #: ../../tutorial/errors.rst:314 msgid "" ">>> def func():\n" "... raise ConnectionError\n" "...\n" ">>> try:\n" "... func()\n" "... except ConnectionError as exc:\n" "... raise RuntimeError('Failed to open database') from exc\n" "...\n" "Traceback (most recent call last):\n" " File \"\", line 2, in \n" " File \"\", line 2, in func\n" "ConnectionError\n" "\n" "The above exception was the direct cause of the following exception:\n" "\n" "Traceback (most recent call last):\n" " File \"\", line 4, in \n" "RuntimeError: Failed to open database" msgstr "" #: ../../tutorial/errors.rst:333 msgid "" "It also allows disabling automatic exception chaining using the ``from " "None`` idiom::" msgstr "它还允许使用 ``from None`` 表达禁用自动异常链::" #: ../../tutorial/errors.rst:336 msgid "" ">>> try:\n" "... open('database.sqlite')\n" "... except OSError:\n" "... raise RuntimeError from None\n" "...\n" "Traceback (most recent call last):\n" " File \"\", line 4, in \n" "RuntimeError" msgstr "" #: ../../tutorial/errors.rst:345 msgid "" "For more information about chaining mechanics, see :ref:`bltin-exceptions`." msgstr "异常链机制详见 :ref:`bltin-exceptions`。" #: ../../tutorial/errors.rst:351 msgid "User-defined Exceptions" msgstr "用户自定义异常" #: ../../tutorial/errors.rst:353 msgid "" "Programs may name their own exceptions by creating a new exception class " "(see :ref:`tut-classes` for more about Python classes). Exceptions should " "typically be derived from the :exc:`Exception` class, either directly or " "indirectly." msgstr "" "程序可以通过创建新的异常类命名自己的异常(Python 类的内容详见 :ref:`tut-classes`)。不论是以直接还是间接的方式,异常都应从 " ":exc:`Exception` 类派生。" #: ../../tutorial/errors.rst:357 msgid "" "Exception classes can be defined which do anything any other class can do, " "but are usually kept simple, often only offering a number of attributes that" " allow information about the error to be extracted by handlers for the " "exception." msgstr "异常类可以被定义成能做其他类所能做的任何事,但通常应当保持简单,它往往只提供一些属性,允许相应的异常处理程序提取有关错误的信息。" #: ../../tutorial/errors.rst:361 msgid "" "Most exceptions are defined with names that end in \"Error\", similar to the" " naming of the standard exceptions." msgstr "大多数异常命名都以 “Error” 结尾,类似标准异常的命名。" #: ../../tutorial/errors.rst:364 msgid "" "Many standard modules define their own exceptions to report errors that may " "occur in functions they define." msgstr "许多标准模块定义了自己的异常,以报告他们定义的函数中可能出现的错误。" #: ../../tutorial/errors.rst:371 msgid "Defining Clean-up Actions" msgstr "定义清理操作" #: ../../tutorial/errors.rst:373 msgid "" "The :keyword:`try` statement has another optional clause which is intended " "to define clean-up actions that must be executed under all circumstances. " "For example::" msgstr ":keyword:`try` 语句还有一个可选子句,用于定义在所有情况下都必须要执行的清理操作。例如:" #: ../../tutorial/errors.rst:377 msgid "" ">>> try:\n" "... raise KeyboardInterrupt\n" "... finally:\n" "... print('Goodbye, world!')\n" "...\n" "Goodbye, world!\n" "Traceback (most recent call last):\n" " File \"\", line 2, in \n" "KeyboardInterrupt" msgstr "" #: ../../tutorial/errors.rst:387 msgid "" "If a :keyword:`finally` clause is present, the :keyword:`!finally` clause " "will execute as the last task before the :keyword:`try` statement completes." " The :keyword:`!finally` clause runs whether or not the :keyword:`!try` " "statement produces an exception. The following points discuss more complex " "cases when an exception occurs:" msgstr "" "如果存在 :keyword:`finally` 子句,则 :keyword:`!finally` 子句是 :keyword:`try` " "语句结束前执行的最后一项任务。不论 :keyword:`!try` 语句是否触发异常,都会执行 :keyword:`!finally` " "子句。以下内容介绍了几种比较复杂的触发异常情景:" #: ../../tutorial/errors.rst:393 msgid "" "If an exception occurs during execution of the :keyword:`!try` clause, the " "exception may be handled by an :keyword:`except` clause. If the exception is" " not handled by an :keyword:`!except` clause, the exception is re-raised " "after the :keyword:`!finally` clause has been executed." msgstr "" "如果执行 :keyword:`!try` 子句期间触发了某个异常,则某个 :keyword:`except` 子句应处理该异常。如果该异常没有 " ":keyword:`!except` 子句处理,在 :keyword:`!finally` 子句执行后会被重新触发。" #: ../../tutorial/errors.rst:399 msgid "" "An exception could occur during execution of an :keyword:`!except` or " ":keyword:`!else` clause. Again, the exception is re-raised after the " ":keyword:`!finally` clause has been executed." msgstr "" ":keyword:`!except` 或 :keyword:`!else` 子句执行期间也会触发异常。 同样,该异常会在 " ":keyword:`!finally` 子句执行之后被重新触发。" #: ../../tutorial/errors.rst:403 msgid "" "If the :keyword:`!finally` clause executes a :keyword:`break`, " ":keyword:`continue` or :keyword:`return` statement, exceptions are not re-" "raised." msgstr "" "如果 :keyword:`!finally` 子句中包含 :keyword:`break`、:keyword:`continue` 或 " ":keyword:`return` 等语句,异常将不会被重新引发。" #: ../../tutorial/errors.rst:407 msgid "" "If the :keyword:`!try` statement reaches a :keyword:`break`, " ":keyword:`continue` or :keyword:`return` statement, the :keyword:`!finally` " "clause will execute just prior to the :keyword:`!break`, " ":keyword:`!continue` or :keyword:`!return` statement's execution." msgstr "" "如果执行 :keyword:`!try` 语句时遇到 :keyword:`break`,、:keyword:`continue` 或 " ":keyword:`return` 语句,则 :keyword:`!finally` 子句在执行 " ":keyword:`!break`、:keyword:`!continue` 或 :keyword:`!return` 语句之前执行。" #: ../../tutorial/errors.rst:413 msgid "" "If a :keyword:`!finally` clause includes a :keyword:`!return` statement, the" " returned value will be the one from the :keyword:`!finally` clause's " ":keyword:`!return` statement, not the value from the :keyword:`!try` " "clause's :keyword:`!return` statement." msgstr "" "如果 :keyword:`!finally` 子句中包含 :keyword:`!return` 语句,则返回值来自 " ":keyword:`!finally` 子句的某个 :keyword:`!return` 语句的返回值,而不是来自 :keyword:`!try` " "子句的 :keyword:`!return` 语句的返回值。" #: ../../tutorial/errors.rst:419 msgid "For example::" msgstr "例如:" #: ../../tutorial/errors.rst:421 msgid "" ">>> def bool_return():\n" "... try:\n" "... return True\n" "... finally:\n" "... return False\n" "...\n" ">>> bool_return()\n" "False" msgstr "" ">>> def bool_return():\n" "... try:\n" "... return True\n" "... finally:\n" "... return False\n" "...\n" ">>> bool_return()\n" "False" #: ../../tutorial/errors.rst:430 msgid "A more complicated example::" msgstr "这是一个比较复杂的例子:" #: ../../tutorial/errors.rst:432 msgid "" ">>> def divide(x, y):\n" "... try:\n" "... result = x / y\n" "... except ZeroDivisionError:\n" "... print(\"division by zero!\")\n" "... else:\n" "... print(\"result is\", result)\n" "... finally:\n" "... print(\"executing finally clause\")\n" "...\n" ">>> divide(2, 1)\n" "result is 2.0\n" "executing finally clause\n" ">>> divide(2, 0)\n" "division by zero!\n" "executing finally clause\n" ">>> divide(\"2\", \"1\")\n" "executing finally clause\n" "Traceback (most recent call last):\n" " File \"\", line 1, in \n" " File \"\", line 3, in divide\n" "TypeError: unsupported operand type(s) for /: 'str' and 'str'" msgstr "" #: ../../tutorial/errors.rst:455 msgid "" "As you can see, the :keyword:`finally` clause is executed in any event. The" " :exc:`TypeError` raised by dividing two strings is not handled by the " ":keyword:`except` clause and therefore re-raised after the " ":keyword:`!finally` clause has been executed." msgstr "" "如上所示,任何情况下都会执行 :keyword:`finally` 子句。:keyword:`except` 子句不处理两个字符串相除触发的 " ":exc:`TypeError`,因此会在 :keyword:`!finally` 子句执行后被重新触发。" #: ../../tutorial/errors.rst:460 msgid "" "In real world applications, the :keyword:`finally` clause is useful for " "releasing external resources (such as files or network connections), " "regardless of whether the use of the resource was successful." msgstr "在实际应用程序中,:keyword:`finally` 子句对于释放外部资源(例如文件或者网络连接)非常有用,无论是否成功使用资源。" #: ../../tutorial/errors.rst:468 msgid "Predefined Clean-up Actions" msgstr "预定义的清理操作" #: ../../tutorial/errors.rst:470 msgid "" "Some objects define standard clean-up actions to be undertaken when the " "object is no longer needed, regardless of whether or not the operation using" " the object succeeded or failed. Look at the following example, which tries " "to open a file and print its contents to the screen. ::" msgstr "" "某些对象定义了不需要该对象时要执行的标准清理操作。无论使用该对象的操作是否成功,都会执行清理操作。比如,下例要打开一个文件,并输出文件内容:" #: ../../tutorial/errors.rst:475 msgid "" "for line in open(\"myfile.txt\"):\n" " print(line, end=\"\")" msgstr "" "for line in open(\"myfile.txt\"):\n" " print(line, end=\"\")" #: ../../tutorial/errors.rst:478 msgid "" "The problem with this code is that it leaves the file open for an " "indeterminate amount of time after this part of the code has finished " "executing. This is not an issue in simple scripts, but can be a problem for " "larger applications. The :keyword:`with` statement allows objects like files" " to be used in a way that ensures they are always cleaned up promptly and " "correctly. ::" msgstr "" "这个代码的问题在于,执行完代码后,文件在一段不确定的时间内处于打开状态。在简单脚本中这没有问题,但对于较大的应用程序来说可能会出问题。:keyword:`with`" " 语句支持以及时、正确的清理的方式使用文件对象:" #: ../../tutorial/errors.rst:484 msgid "" "with open(\"myfile.txt\") as f:\n" " for line in f:\n" " print(line, end=\"\")" msgstr "" "with open(\"myfile.txt\") as f:\n" " for line in f:\n" " print(line, end=\"\")" #: ../../tutorial/errors.rst:488 msgid "" "After the statement is executed, the file *f* is always closed, even if a " "problem was encountered while processing the lines. Objects which, like " "files, provide predefined clean-up actions will indicate this in their " "documentation." msgstr "语句执行完毕后,即使在处理行时遇到问题,都会关闭文件 *f*。和文件一样,支持预定义清理操作的对象会在文档中指出这一点。" #: ../../tutorial/errors.rst:496 msgid "Raising and Handling Multiple Unrelated Exceptions" msgstr "引发和处理多个不相关的异常" #: ../../tutorial/errors.rst:498 msgid "" "There are situations where it is necessary to report several exceptions that" " have occurred. This is often the case in concurrency frameworks, when " "several tasks may have failed in parallel, but there are also other use " "cases where it is desirable to continue execution and collect multiple " "errors rather than raise the first exception." msgstr "" "在有些情况下,有必要报告几个已经发生的异常。这通常是在并发框架中当几个任务并行失败时的情况,但也有其他的用例,有时需要是继续执行并收集多个错误而不是引发第一个异常。" #: ../../tutorial/errors.rst:504 msgid "" "The builtin :exc:`ExceptionGroup` wraps a list of exception instances so " "that they can be raised together. It is an exception itself, so it can be " "caught like any other exception. ::" msgstr "" "内置的 :exc:`ExceptionGroup` " "打包了一个异常实例的列表,这样它们就可以一起被引发。它本身就是一个异常,所以它可以像其他异常一样被捕获。" #: ../../tutorial/errors.rst:508 msgid "" ">>> def f():\n" "... excs = [OSError('error 1'), SystemError('error 2')]\n" "... raise ExceptionGroup('there were problems', excs)\n" "...\n" ">>> f()\n" " + Exception Group Traceback (most recent call last):\n" " | File \"\", line 1, in \n" " | File \"\", line 3, in f\n" " | ExceptionGroup: there were problems\n" " +-+---------------- 1 ----------------\n" " | OSError: error 1\n" " +---------------- 2 ----------------\n" " | SystemError: error 2\n" " +------------------------------------\n" ">>> try:\n" "... f()\n" "... except Exception as e:\n" "... print(f'caught {type(e)}: e')\n" "...\n" "caught : e\n" ">>>" msgstr "" #: ../../tutorial/errors.rst:530 msgid "" "By using ``except*`` instead of ``except``, we can selectively handle only " "the exceptions in the group that match a certain type. In the following " "example, which shows a nested exception group, each ``except*`` clause " "extracts from the group exceptions of a certain type while letting all other" " exceptions propagate to other clauses and eventually to be reraised. ::" msgstr "" "通过使用 ``except*`` 代替 ``except`` " ",我们可以有选择地只处理组中符合某种类型的异常。在下面的例子中,显示了一个嵌套的异常组,每个 ``except*`` " "子句都从组中提取了某种类型的异常,而让所有其他的异常传播到其他子句,并最终被重新引发。" #: ../../tutorial/errors.rst:537 msgid "" ">>> def f():\n" "... raise ExceptionGroup(\n" "... \"group1\",\n" "... [\n" "... OSError(1),\n" "... SystemError(2),\n" "... ExceptionGroup(\n" "... \"group2\",\n" "... [\n" "... OSError(3),\n" "... RecursionError(4)\n" "... ]\n" "... )\n" "... ]\n" "... )\n" "...\n" ">>> try:\n" "... f()\n" "... except* OSError as e:\n" "... print(\"There were OSErrors\")\n" "... except* SystemError as e:\n" "... print(\"There were SystemErrors\")\n" "...\n" "There were OSErrors\n" "There were SystemErrors\n" " + Exception Group Traceback (most recent call last):\n" " | File \"\", line 2, in \n" " | File \"\", line 2, in f\n" " | ExceptionGroup: group1\n" " +-+---------------- 1 ----------------\n" " | ExceptionGroup: group2\n" " +-+---------------- 1 ----------------\n" " | RecursionError: 4\n" " +------------------------------------\n" ">>>" msgstr "" #: ../../tutorial/errors.rst:573 msgid "" "Note that the exceptions nested in an exception group must be instances, not" " types. This is because in practice the exceptions would typically be ones " "that have already been raised and caught by the program, along the following" " pattern::" msgstr "注意,嵌套在一个异常组中的异常必须是实例,而不是类型。这是因为在实践中,这些异常通常是那些已经被程序提出并捕获的异常,其模式如下::" #: ../../tutorial/errors.rst:578 msgid "" ">>> excs = []\n" "... for test in tests:\n" "... try:\n" "... test.run()\n" "... except Exception as e:\n" "... excs.append(e)\n" "...\n" ">>> if excs:\n" "... raise ExceptionGroup(\"Test Failures\", excs)\n" "..." msgstr "" ">>> excs = []\n" "... for test in tests:\n" "... try:\n" "... test.run()\n" "... except Exception as e:\n" "... excs.append(e)\n" "...\n" ">>> if excs:\n" "... raise ExceptionGroup(\"Test Failures\", excs)\n" "..." #: ../../tutorial/errors.rst:593 msgid "Enriching Exceptions with Notes" msgstr "用注释细化异常情况" #: ../../tutorial/errors.rst:595 msgid "" "When an exception is created in order to be raised, it is usually " "initialized with information that describes the error that has occurred. " "There are cases where it is useful to add information after the exception " "was caught. For this purpose, exceptions have a method ``add_note(note)`` " "that accepts a string and adds it to the exception's notes list. The " "standard traceback rendering includes all notes, in the order they were " "added, after the exception. ::" msgstr "" "当一个异常被创建以引发时,它通常被初始化为描述所发生错误的信息。在有些情况下,在异常被捕获后添加信息是很有用的。为了这个目的,异常有一个 " "``add_note(note)`` 方法接受一个字符串,并将其添加到异常的注释列表。标准的回溯在异常之后按照它们被添加的顺序呈现包括所有的注释。 ::" #: ../../tutorial/errors.rst:602 msgid "" ">>> try:\n" "... raise TypeError('bad type')\n" "... except Exception as e:\n" "... e.add_note('Add some information')\n" "... e.add_note('Add some more information')\n" "... raise\n" "...\n" "Traceback (most recent call last):\n" " File \"\", line 2, in \n" "TypeError: bad type\n" "Add some information\n" "Add some more information\n" ">>>" msgstr "" #: ../../tutorial/errors.rst:616 msgid "" "For example, when collecting exceptions into an exception group, we may want" " to add context information for the individual errors. In the following each" " exception in the group has a note indicating when this error has occurred. " "::" msgstr "" "例如,当把异常收集到一个异常组时,我们可能想为各个错误添加上下文信息。在下文中,组中的每个异常都有一个说明,指出这个错误是什么时候发生的。 ::" #: ../../tutorial/errors.rst:620 msgid "" ">>> def f():\n" "... raise OSError('operation failed')\n" "...\n" ">>> excs = []\n" ">>> for i in range(3):\n" "... try:\n" "... f()\n" "... except Exception as e:\n" "... e.add_note(f'Happened in Iteration {i+1}')\n" "... excs.append(e)\n" "...\n" ">>> raise ExceptionGroup('We have some problems', excs)\n" " + Exception Group Traceback (most recent call last):\n" " | File \"\", line 1, in \n" " | ExceptionGroup: We have some problems (3 sub-exceptions)\n" " +-+---------------- 1 ----------------\n" " | Traceback (most recent call last):\n" " | File \"\", line 3, in \n" " | File \"\", line 2, in f\n" " | OSError: operation failed\n" " | Happened in Iteration 1\n" " +---------------- 2 ----------------\n" " | Traceback (most recent call last):\n" " | File \"\", line 3, in \n" " | File \"\", line 2, in f\n" " | OSError: operation failed\n" " | Happened in Iteration 2\n" " +---------------- 3 ----------------\n" " | Traceback (most recent call last):\n" " | File \"\", line 3, in \n" " | File \"\", line 2, in f\n" " | OSError: operation failed\n" " | Happened in Iteration 3\n" " +------------------------------------\n" ">>>" msgstr ""