标签归档:deprecated

如何在Python中忽略弃用警告

问题:如何在Python中忽略弃用警告

我不断得到这个:

DeprecationWarning: integer argument expected, got float

我如何使此消息消失?有没有一种方法可以避免Python中的警告?

I keep getting this :

DeprecationWarning: integer argument expected, got float

How do I make this message go away? Is there a way to avoid warnings in Python?


回答 0

warnings模块的文档中:

 #!/usr/bin/env python -W ignore::DeprecationWarning

如果您使用的是Windows,请-W ignore::DeprecationWarning作为参数传递给Python。最好通过强制转换为int来解决问题。

(请注意,在Python 3.2中,默认情况下会忽略弃用警告。)

From documentation of the warnings module:

 #!/usr/bin/env python -W ignore::DeprecationWarning

If you’re on Windows: pass -W ignore::DeprecationWarning as an argument to Python. Better though to resolve the issue, by casting to int.

(Note that in Python 3.2, deprecation warnings are ignored by default.)


回答 1

您应该只修复代码,以防万一,

import warnings
warnings.filterwarnings("ignore", category=DeprecationWarning) 

You should just fix your code but just in case,

import warnings
warnings.filterwarnings("ignore", category=DeprecationWarning) 

回答 2

我有这些:

/home/eddyp/virtualenv/lib/python2.6/site-packages/Twisted-8.2.0-py2.6-linux-x86_64.egg/twisted/persisted/sob.py:12:
DeprecationWarning: the md5 module is deprecated; use hashlib instead import os, md5, sys

/home/eddyp/virtualenv/lib/python2.6/site-packages/Twisted-8.2.0-py2.6-linux-x86_64.egg/twisted/python/filepath.py:12:
DeprecationWarning: the sha module is deprecated; use the hashlib module instead import sha

使用以下方法修复了该问题:

import warnings

with warnings.catch_warnings():
    warnings.filterwarnings("ignore",category=DeprecationWarning)
    import md5, sha

yourcode()

现在您仍然得到所有其他DeprecationWarnings,但不是由以下原因引起的:

import md5, sha

I had these:

/home/eddyp/virtualenv/lib/python2.6/site-packages/Twisted-8.2.0-py2.6-linux-x86_64.egg/twisted/persisted/sob.py:12:
DeprecationWarning: the md5 module is deprecated; use hashlib instead import os, md5, sys

/home/eddyp/virtualenv/lib/python2.6/site-packages/Twisted-8.2.0-py2.6-linux-x86_64.egg/twisted/python/filepath.py:12:
DeprecationWarning: the sha module is deprecated; use the hashlib module instead import sha

Fixed it with:

import warnings

with warnings.catch_warnings():
    warnings.filterwarnings("ignore",category=DeprecationWarning)
    import md5, sha

yourcode()

Now you still get all the other DeprecationWarnings, but not the ones caused by:

import md5, sha

回答 3

我发现最干净的方法(尤其是在Windows上)是通过将以下内容添加到C:\ Python26 \ Lib \ site-packages \ sitecustomize.py:

import warnings
warnings.filterwarnings("ignore", category=DeprecationWarning)

请注意,我必须创建此文件。当然,如果您的路径不同,请更改python的路径。

I found the cleanest way to do this (especially on windows) is by adding the following to C:\Python26\Lib\site-packages\sitecustomize.py:

import warnings
warnings.filterwarnings("ignore", category=DeprecationWarning)

Note that I had to create this file. Of course, change the path to python if yours is different.


回答 4

这些答案都不适合我,因此我将发布解决方法。我使用以下at the beginning of my main.py脚本,它运行正常。


照原样使用以下内容(复制粘贴):

def warn(*args, **kwargs):
    pass
import warnings
warnings.warn = warn

例:

import "blabla"
import "blabla"

def warn(*args, **kwargs):
    pass
import warnings
warnings.warn = warn

# more code here...
# more code here...

None of these answers worked for me so I will post my way to solve this. I use the following at the beginning of my main.py script and it works fine.


Use the following as it is (copy-paste it):

def warn(*args, **kwargs):
    pass
import warnings
warnings.warn = warn

Example:

import "blabla"
import "blabla"

def warn(*args, **kwargs):
    pass
import warnings
warnings.warn = warn

# more code here...
# more code here...


回答 5

通过正确的论点?:P

更严重的是,您可以在命令行上将参数-Wi :: DeprecationWarning传递给解释器,以忽略弃用警告。

Pass the correct arguments? :P

On the more serious note, you can pass the argument -Wi::DeprecationWarning on the command line to the interpreter to ignore the deprecation warnings.


回答 6

将参数转换为int。就这么简单

int(argument)

Convert the argument to int. It’s as simple as

int(argument)

回答 7

当您只想在功能中忽略警告时,可以执行以下操作。

import warnings
from functools import wraps


def ignore_warnings(f):
    @wraps(f)
    def inner(*args, **kwargs):
        with warnings.catch_warnings(record=True) as w:
            warnings.simplefilter("ignore")
            response = f(*args, **kwargs)
        return response
    return inner

@ignore_warnings
def foo(arg1, arg2):
    ...
    write your code here without warnings
    ...

@ignore_warnings
def foo2(arg1, arg2, arg3):
    ...
    write your code here without warnings
    ...

只需在要忽略所有警告的函数上添加@ignore_warnings装饰器

When you want to ignore warnings only in functions you can do the following.

import warnings
from functools import wraps


def ignore_warnings(f):
    @wraps(f)
    def inner(*args, **kwargs):
        with warnings.catch_warnings(record=True) as w:
            warnings.simplefilter("ignore")
            response = f(*args, **kwargs)
        return response
    return inner

@ignore_warnings
def foo(arg1, arg2):
    ...
    write your code here without warnings
    ...

@ignore_warnings
def foo2(arg1, arg2, arg3):
    ...
    write your code here without warnings
    ...

Just add the @ignore_warnings decorator on the function you want to ignore all warnings


回答 8

Docker解决方案

  • 在运行python应用程序之前禁用所有警告
    • 您也可以禁用dockerized测试
ENV PYTHONWARNINGS="ignore::DeprecationWarning"

Docker Solution

  • Disable ALL warnings before running the python application
    • You can disable your dockerized tests as well
ENV PYTHONWARNINGS="ignore::DeprecationWarning"

回答 9

如果您使用的是Python3,请尝试以下代码:

import sys

if not sys.warnoptions:
    import warnings
    warnings.simplefilter("ignore")

或尝试这个…

import warnings

def fxn():
    warnings.warn("deprecated", DeprecationWarning)

with warnings.catch_warnings():
    warnings.simplefilter("ignore")
    fxn()

或尝试这个…

import warnings
warnings.filterwarnings("ignore")

Try the below code if you’re Using Python3:

import sys

if not sys.warnoptions:
    import warnings
    warnings.simplefilter("ignore")

or try this…

import warnings

def fxn():
    warnings.warn("deprecated", DeprecationWarning)

with warnings.catch_warnings():
    warnings.simplefilter("ignore")
    fxn()

or try this…

import warnings
warnings.filterwarnings("ignore")

回答 10

Python 3

在编写代码之前,只需在容易记住的几行下面编写代码:

import warnings

warnings.filterwarnings("ignore")

Python 3

Just write below lines that are easy to remember before writing your code:

import warnings

warnings.filterwarnings("ignore")

回答 11

如果您知道自己在做什么,另一种方法就是简单地找到警告您的文件(该文件的路径显示在警告信息中),对生成警告的行进行注释。

If you know what you are doing, another way is simply find the file that warns you(the path of the file is shown in warning info), comment the lines that generate the warnings.


回答 12

对于python 3,只需编写以下代码即可忽略所有警告。

from warnings import filterwarnings
filterwarnings("ignore")

For python 3, just write below codes to ignore all warnings.

from warnings import filterwarnings
filterwarnings("ignore")

回答 13

不会打扰您,但会警告您,下次升级python时,您正在做的事情可能会停止工作。转换为int并完成它。

顺便说一句。您还可以编写自己的警告处理程序。只需分配一个不执行任何操作的函数即可。 如何将python警告重定向到自定义流?

Not to beat you up about it but you are being warned that what you are doing will likely stop working when you next upgrade python. Convert to int and be done with it.

BTW. You can also write your own warnings handler. Just assign a function that does nothing. How to redirect python warnings to a custom stream?


Python的字符串格式化的许多方式-较旧的(即将被淘汰)吗?

问题:Python的字符串格式化的许多方式-较旧的(即将被淘汰)吗?

Python至少有六种格式化字符串的方式:

In [1]: world = "Earth"

# method 1a
In [2]: "Hello, %s" % world
Out[2]: 'Hello, Earth'

# method 1b
In [3]: "Hello, %(planet)s" % {"planet": world}
Out[3]: 'Hello, Earth'

# method 2a
In [4]: "Hello, {0}".format(world)
Out[4]: 'Hello, Earth'

# method 2b
In [5]: "Hello, {planet}".format(planet=world)
Out[5]: 'Hello, Earth'

# method 2c
In [6]: f"Hello, {world}"
Out[6]: 'Hello, Earth'

In [7]: from string import Template

# method 3
In [8]: Template("Hello, $planet").substitute(planet=world)
Out[8]: 'Hello, Earth'

不同方法的简要历史:

  • printf自从Python诞生以来,样式样式格式化就已经存在
  • Template班是在Python 2.4中引入
  • format方法在Python 2.6中引入
  • f-strings是在Python 3.6中引入的

我的问题是:

  • 是否printf不赞成使用-style格式?
  • 在中Template class,该substitute方法是否已弃用或将要弃用?(我不是在谈论safe_substitute,据我所知它提供了独特的功能)

类似的问题以及为什么我认为它们不是重复的:

也可以看看

Python has at least six ways of formatting a string:

In [1]: world = "Earth"

# method 1a
In [2]: "Hello, %s" % world
Out[2]: 'Hello, Earth'

# method 1b
In [3]: "Hello, %(planet)s" % {"planet": world}
Out[3]: 'Hello, Earth'

# method 2a
In [4]: "Hello, {0}".format(world)
Out[4]: 'Hello, Earth'

# method 2b
In [5]: "Hello, {planet}".format(planet=world)
Out[5]: 'Hello, Earth'

# method 2c
In [6]: f"Hello, {world}"
Out[6]: 'Hello, Earth'

In [7]: from string import Template

# method 3
In [8]: Template("Hello, $planet").substitute(planet=world)
Out[8]: 'Hello, Earth'

A brief history of the different methods:

  • printf-style formatting has been around since Pythons infancy
  • The Template class was introduced in Python 2.4
  • The format method was introduced in Python 2.6
  • f-strings were introduced in Python 3.6

My questions are:

  • Is printf-style formatting deprecated or going to be deprecated?
  • In the Template class, is the substitute method deprecated or going to be deprecated? (I’m not talking about safe_substitute, which as I understand it offers unique capabilities)

Similar questions and why I think they’re not duplicates:

  • Python string formatting: % vs. .format — treats only methods 1 and 2, and asks which one is better; my question is explicitly about deprecation in the light of the Zen of Python

  • String formatting options: pros and cons — treats only methods 1a and 1b in the question, 1 and 2 in the answer, and also nothing about deprecation

  • advanced string formatting vs template strings — mostly about methods 1 and 3, and doesn’t address deprecation

  • String formatting expressions (Python) — answer mentions that the original ‘%’ approach is planned to be deprecated. But what’s the difference between planned to be deprecated, pending deprecation and actual deprecation? And the printf-style method doesn’t raise even a PendingDeprecationWarning, so is this really going to be deprecated? This post is also quite old, so the information may be outdated.

See also


回答 0

尽管在文档中有各种各样的迹象表明,.formatf字符串优于%字符串,但尚无可行的方案来弃用后者。

在提交的问题#14123中:明确提及旧样式%字符串格式有一些警告,但不会很快消失。,受问题启发,表明目前没有计划弃用printf样式格式,有关%-formatting 的文档已被编辑为包含以下短语:

由于新的字符串格式语法更加灵活并且可以自然地处理元组和字典,因此建议将其用于新代码。但是,目前没有废弃过printf样式格式的计划

(强调我的。)

此短语稍后在commit Close#4966中删除:修改序列文档,以更好地解释现代Python的状态。这看起来似乎是一个迹象,表明不再支持%格式化的计划已经重新出现在卡上了……但是,深入研究Bug跟踪程序后,发现其意图恰恰相反。在错误跟踪器上,提交的作者描述了更改的特征,如下所示

  • 更改了描述printf样式格式与str.format方法之间关系的散文(故意消除了前者可能会消失的真正危险的暗示-认真考虑将其销毁是不切实际的)

换句话说,我们对%-formatting文档进行了两次连续更改,旨在明确强调不会被弃用,更不用说删除了。这些文档仍然对不同类型的字符串格式的相对优点持保留意见,但他们也清楚%格式不会被弃用或删除。

更重要的是,该段落的最新更改是在2017年3月,对此进行了更改…

此处描述的格式化操作表现出各种古怪,这些古怪会导致许多常见错误(例如无法正确显示元组和字典)。使用较新的格式化字符串文字或str.format接口有助于避免这些错误。这些替代方法还提供了更强大,灵活和可扩展的文本格式设置方法。

…对此:

此处描述的格式化操作表现出各种古怪,这些古怪会导致许多常见错误(例如无法正确显示元组和字典)。使用更新的格式化字符串文字,str.format接口或模板字符串可能有助于避免这些错误。这些选择中的每一个都提供了自己的权衡,并带来了简单性,灵活性和/或可扩展性的好处。

请注意,从“避免使用帮助”到“可以避免使用”的变化,以及关于.formatf和弦的清晰建议如何被蓬松,模棱两可的散文所取代,有关每种样式如何“提供自己的取舍和好处”。也就是说,不仅不再正式弃用卡片,而且当前的文档公开承认%格式至少比其他方法具有一些“好处”。

从这一切中我可以推断出,弃用或删除%格式的运动不仅步履蹒跚,而且被彻底永久地击败。

While there are various indications in the docs that .format and f-strings are superior to % strings, there’s no surviving plan to ever deprecate the latter.

In commit Issue #14123: Explicitly mention that old style % string formatting has caveats but is not going away any time soon., inspired by issue Indicate that there are no current plans to deprecate printf-style formatting, the docs on %-formatting were edited to contain this phrase:

As the new string-formatting syntax is more flexible and handles tuples and dictionaries naturally, it is recommended for new code. However, there are no current plans to deprecate printf-style formatting.

(Emphasis mine.)

This phrase was removed later, in commit Close #4966: revamp the sequence docs in order to better explain the state of modern Python. This might seem like a sign that a plan to deprecate % formatting was back on the cards… but diving into the bug tracker reveals that the intent was the opposite. On the bug tracker, the author of the commit characterises the change like this:

  • changed the prose that describes the relationship between printf-style formatting and the str.format method (deliberately removing the implication that the former is any real danger of disappearing – it’s simply not practical for us to seriously contemplate killing it off)

In other words, we’ve had two consecutive changes to the %-formatting docs intended to explicitly emphasise that it will not be deprecated, let alone removed. The docs remain opinionated on the relative merits of different kinds of string formatting, but they’re also clear the %-formatting isn’t going to get deprecated or removed.

What’s more, the most recent change to that paragraph, in March 2017, changed it from this…

The formatting operations described here exhibit a variety of quirks that lead to a number of common errors (such as failing to display tuples and dictionaries correctly). Using the newer formatted string literals or the str.format interface helps avoid these errors. These alternatives also provide more powerful, flexible and extensible approaches to formatting text.

… to this:

The formatting operations described here exhibit a variety of quirks that lead to a number of common errors (such as failing to display tuples and dictionaries correctly). Using the newer formatted string literals, the str.format interface, or template strings may help avoid these errors. Each of these alternatives provides their own trade-offs and benefits of simplicity, flexibility, and/or extensibility.

Notice the change from “helps avoid” to “may help avoid”, and how the clear recommendation of .format and f-strings has been replaced by fluffy, equivocal prose about how each style “provides their own trade-offs and benefits”. That is, not only is a formal deprecation no longer on the cards, but the current docs are openly acknowledging that % formatting at least has some “benefits” over the other approaches.

I’d infer from all this that the movement to deprecate or remove % formatting has not only faltered, but been defeated thoroughly and permanently.


回答 1

.format()方法旨在替换旧的%格式语法。后者已经不再强调,(但没有正式弃用尚未)。方法文档指出:

字符串格式化的这种方法是在Python 3的新标准,并应首选%格式化中所描述的字符串的格式化操作在新的代码。

(强调我的)。

为了保持向后兼容性,并让您更容易过渡,旧格式已经被留在原地现在。根据最初的PEP 3101提案

向后兼容

可以通过保留现有机制来保持向后兼容性。新系统不会与现有字符串格式化技术的任何方法名称发生冲突,因此这两个系统可以共存,直到需要弃用旧系统为止。

请注意,直到该淘汰旧系统为止;它尚未被弃用,但是只要您编写新代码,就将使用新系统

新系统的一个优点是您可以结合使用旧%格式化程序的元组和字典方法:

"{greeting}, {0}".format(world, greeting='Hello')

并可以通过 object.__format__()用于处理各个值格式钩子进行。

请注意,旧系统具有%Template类,后者允许您创建添加或更改其行为的子类。新型系统具有Formatter一流填充相同细分市场。

Python 3进一步远离了弃用,而是在printf-style String Formatting部分中给您警告:

注意:此处描述的格式化操作表现出各种古怪,导致许多常见错误(例如未能正确显示元组和字典)。使用较新的格式化字符串文字str.format()接口有助于避免这些错误。这些替代方法还提供了更强大,灵活和可扩展的文本格式设置方法。

Python 3.6还添加了格式化的字符串文字,将表达式内联格式字符串中。这些是使用内插值创建字符串的最快方法,应使用它,而不是str.format()在可以使用文字的任何地方。

The new .format() method is meant to replace the old % formatting syntax. The latter has been de-emphasised, (but not officially deprecated yet). The method documentation states as much:

This method of string formatting is the new standard in Python 3, and should be preferred to the % formatting described in String Formatting Operations in new code.

(Emphasis mine).

To maintain backwards compatibility and to make transition easier, the old format has been left in place for now. From the original PEP 3101 proposal:

Backwards Compatibility

Backwards compatibility can be maintained by leaving the existing mechanisms in place. The new system does not collide with any of the method names of the existing string formatting techniques, so both systems can co-exist until it comes time to deprecate the older system.

Note the until it comes time to deprecate the older system; it hasn’t been deprecated, but the new system is to be used whenever you write new code.

The new system has as an advantage that you can combine the tuple and dictionary approach of the old % formatter:

"{greeting}, {0}".format(world, greeting='Hello')

and is extensible through the object.__format__() hook used to handle formatting of individual values.

Note that the old system had % and the Template class, where the latter allows you to create subclasses that add or alter its behaviour. The new-style system has the Formatter class to fill the same niche.

Python 3 has further stepped away from deprecation, instead giving you warning in the printf-style String Formatting section:

Note: The formatting operations described here exhibit a variety of quirks that lead to a number of common errors (such as failing to display tuples and dictionaries correctly). Using the newer formatted string literals or the str.format() interface helps avoid these errors. These alternatives also provide more powerful, flexible and extensible approaches to formatting text.

Python 3.6 also added formatted string literals, which in-line the expressions into the format strings. These are the fastest method of creating strings with interpolated values, and should be used instead of str.format() wherever you can use a literal.


回答 2

%尽管有其他答案,但不建议使用字符串格式的运算符,并且不会删除该运算符。
每次在Python开发列表中提出该主题时,都会有一个关于哪个更好的参数,但是对于是否要删除经典方法却没有争议-它会一直存在。尽管在PEP 3101上有说明,但Python 3.1来了又去了,%格式化仍然存在。

保持经典风格的说法很明确:它很简单,很快,可以快速完成简短的事情。使用该.format方法并不总是那么容易理解-几乎没有人-即使在核心开发人员中,也可以使用所提供的完整语法,.format而无需查看参考资料甚至在2009年,就有这样的消息:http:// mail。 python.org/pipermail/python-dev/2009-October/092529.html 几乎没有出现该主题。

2016年更新

在当前的Python开发版本(将成为Python 3.6)中,有第三种字符串内插方法,如PEP-0498所述。它定义了一个新的报价前缀f""(除了当前的u""b""r"")。

给字符串加上前缀f将在运行时在字符串对象上调用一个方法,该方法将自动将当前作用域中的变量插入到字符串中:

>>> value = 80
>>> f'The value is {value}.'
'The value is 80.'

The % operator for string formatting is not deprecated, and is not going to be removed – despite the other answers.
Every time the subject is raised on Python development list, there is strong controversy on which is better, but no controversy on whether to remove the classic way – it will stay. Despite being denoted on PEP 3101, Python 3.1 had come and gone, and % formatting is still around.

The statements for the keeping classic style are clear: it is simple, it is fast, it is quick to do for short things. Using the .format method is not always more readable – and barely anyone – even among the core developers, can use the full syntax provided by .format without having to look at the reference Even back in 2009, one had messages like this: http://mail.python.org/pipermail/python-dev/2009-October/092529.html – the subject had barely showed up in the lists since.

2016 update

In current Python development version (which will become Python 3.6) there is a third method of string interpolation, described on PEP-0498. It defines a new quote prefix f"" (besides the current u"", b"" and r"").

Prefixing a string by f will call a method on the string object at runtime, which will automatically interpolate variables from the current scope into the string:

>>> value = 80
>>> f'The value is {value}.'
'The value is 80.'

回答 3

圭多对此的最新立场似乎在这里指出:

Python 3.0的新增功能

PEP 3101:字符串格式化的新方法

用于内置字符串格式化操作的新系统取代了%字符串格式化运算符。(但是,仍然支持%运算符;它将在Python 3.1中弃用,并在以后的某个时间从语言中删除。)有关完整说明,请阅读PEP 3101。

PEP3101本身,它有最后的修改可以追溯到(周五,2011年9月30日),这样的晚的,一个没有进步,我想。

Guido’s latest position on this seems to be indicated here:

What’s New In Python 3.0

PEP 3101: A New Approach To String Formatting

A new system for built-in string formatting operations replaces the % string formatting operator. (However, the % operator is still supported; it will be deprecated in Python 3.1 and removed from the language at some later time.) Read PEP 3101 for the full scoop.

And the PEP3101 itself, which has the last modified dating back to (Fri, 30 Sep 2011), so no progress as of late on that one, I suppose.


回答 4

在查看较旧的Python文档和PEP 3101时,有一条语句表示将来将不推荐使用%运算符并将其从该语言中删除。在下面的语句是在Python文档的Python 3.0,3.1和3.2:

由于str.format()很新,因此许多Python代码仍然使用%运算符。但是,由于最终会从该语言中删除这种旧的格式设置样式,因此通常应使用str.format()。

如果转到Python 3.3和3.4文档中的同一部分,您将看到该语句已被删除。我也无法在文档中的任何其他地方找到任何其他声明,表明该运算符将不推荐使用或从该语言中删除。还需要注意的是,PEP3101两年半没有进行过修改(2011年9月30日,星期五)。

更新资料

PEP461接受将%格式添加到字节和字节数组中,并且应该是Python 3.5或3.6的一部分。这是%运算符还活着而且在踢的另一个迹象。

Looking at the older Python docs and PEP 3101 there was a statement that the % operator will be deprecated and removed from the language in the future. The following statement was in the Python docs for Python 3.0, 3.1, and 3.2:

Since str.format() is quite new, a lot of Python code still uses the % operator. However, because this old style of formatting will eventually be removed from the language, str.format() should generally be used.

If you go to the same section in Python 3.3 and 3.4 docs, you will see that statement has been removed. I also cannot find any other statement anywhere else in the documentation indicating that the operator will be deprecated or removed from the language. It’s also important to note that PEP3101 has not been modified in over two and a half years (Fri, 30 Sep 2011).

Update

PEP461 Adding % formatting to bytes and bytearray is accepted and should be part of Python 3.5 or 3.6. It’s another sign that the % operator is alive and kicking.


Python 2.6中不推荐使用BaseException.message

问题:Python 2.6中不推荐使用BaseException.message

当我使用以下用户定义的异常时,我收到一条警告:Python 2.6中不推荐使用BaseException.message:

class MyException(Exception):

    def __init__(self, message):
        self.message = message

    def __str__(self):
        return repr(self.message)

这是警告:

DeprecationWarning: BaseException.message has been deprecated as of Python 2.6
self.message = message

这怎么了 我要更改什么以摆脱过时警告?

I get a warning that BaseException.message is deprecated in Python 2.6 when I use the following user-defined exception:

class MyException(Exception):

    def __init__(self, message):
        self.message = message

    def __str__(self):
        return repr(self.message)

This is the warning:

DeprecationWarning: BaseException.message has been deprecated as of Python 2.6
self.message = message

What’s wrong with this? What do I have to change to get rid of the deprecation warning?


回答 0

解决方案-几乎不需要编码

只是继承您的异常类,Exception并将消息作为第一个参数传递给构造函数

例:

class MyException(Exception):
    """My documentation"""

try:
    raise MyException('my detailed description')
except MyException as my:
    print my # outputs 'my detailed description'

您可以使用str(my)或(不太优雅)my.args[0]来访问自定义消息。

背景

在较新的Python版本(从2.6开始)中,我们应该从Exception(从Python 2.5开始)继承自BaseException的自定义异常类中继承。在PEP 352中详细描述了背景。

class BaseException(object):

    """Superclass representing the base of the exception hierarchy.
    Provides an 'args' attribute that contains all arguments passed
    to the constructor.  Suggested practice, though, is that only a
    single string argument be passed to the constructor."""

__str__并且__repr__已经以有意义的方式实现,尤其是对于仅一个arg(可用作消息)的情况。

您无需重复__str____init__实施或创建_get_message其他人建议的内容。

Solution – almost no coding needed

Just inherit your exception class from Exception and pass the message as the first parameter to the constructor

Example:

class MyException(Exception):
    """My documentation"""

try:
    raise MyException('my detailed description')
except MyException as my:
    print my # outputs 'my detailed description'

You can use str(my) or (less elegant) my.args[0] to access the custom message.

Background

In the newer versions of Python (from 2.6) we are supposed to inherit our custom exception classes from Exception which (starting from Python 2.5) inherits from BaseException. The background is described in detail in PEP 352.

class BaseException(object):

    """Superclass representing the base of the exception hierarchy.
    Provides an 'args' attribute that contains all arguments passed
    to the constructor.  Suggested practice, though, is that only a
    single string argument be passed to the constructor."""

__str__ and __repr__ are already implemented in a meaningful way, especially for the case of only one arg (that can be used as message).

You do not need to repeat __str__ or __init__ implementation or create _get_message as suggested by others.


回答 1

是的,它在Python 2.6中已弃用,因为它在Python 3.0中已经不存在了

BaseException类不再提供存储错误消息的方法。您必须自己实施。您可以使用一个子类来执行此操作,该子类使用用于存储消息的属性。

class MyException(Exception):
    def _get_message(self): 
        return self._message
    def _set_message(self, message): 
        self._message = message
    message = property(_get_message, _set_message)

希望这可以帮助

Yes, it’s deprecated in Python 2.6 because it’s going away in Python 3.0

BaseException class does not provide a way to store error message anymore. You’ll have to implement it yourself. You can do this with a subclass that uses a property for storing the message.

class MyException(Exception):
    def _get_message(self): 
        return self._message
    def _set_message(self, message): 
        self._message = message
    message = property(_get_message, _set_message)

Hope this helps


回答 2

class MyException(Exception):

    def __str__(self):
        return repr(self.args[0])

e = MyException('asdf')
print e

这是您使用Python2.6样式的类。新的异常采用任意数量的参数。

class MyException(Exception):

    def __str__(self):
        return repr(self.args[0])

e = MyException('asdf')
print e

This is your class in Python2.6 style. The new exception takes an arbitrary number of arguments.


回答 3

如何复制警告

让我澄清一下问题,因为您无法使用问题的示例代码来复制此问题,如果您启用了警告(通过-WflagPYTHONWARNINGSenvironment变量或warnings模块),则会在Python 2.6和2.7中复制警告:

>>> error = Exception('foobarbaz')
>>> error.message
__main__:1: DeprecationWarning: BaseException.message has been deprecated as of Python 2.6
'foobarbaz'

停止使用 .message

我更喜欢使用repr(error),它返回一个字符串,其中包含错误类型的名称,消息的repr(如果有的话)以及其余参数的repr。

>>> repr(error)
"Exception('foobarbaz',)"

仍在使用时消除警告 .message

你得到的方式干掉DeprecationWarning是继承一个内置的exceptions,因为Python的设计意图:

class MyException(Exception):

    def __init__(self, message, *args):
        self.message = message
        # delegate the rest of initialization to parent
        super(MyException, self).__init__(message, *args)

>>> myexception = MyException('my message')
>>> myexception.message
'my message'
>>> str(myexception)
'my message'
>>> repr(myexception)
"MyException('my message',)"

只获得.message属性而没有error.message

如果您知道要向Exception发送一个参数,即一条消息,这就是您想要的,那么最好避免使用message属性,而只处理str错误。说一个子类Exception

class MyException(Exception):
    '''demo straight subclass'''

和用法:

>>> myexception = MyException('my message')
>>> str(myexception)
'my message'

另请参阅以下答案:

在现代Python中声明自定义异常的正确方法?

How to replicate the warning

Let me clarify the problem, as one cannot replicate this with the question’s sample code, this will replicate the warning in Python 2.6 and 2.7, if you have warnings turned on (via the -W flag, the PYTHONWARNINGS environment variable, or the warnings module):

>>> error = Exception('foobarbaz')
>>> error.message
__main__:1: DeprecationWarning: BaseException.message has been deprecated as of Python 2.6
'foobarbaz'

Stop using .message

I prefer repr(error), which returns a string that contains the name of the error type, the repr of the message, if there is one, and the repr of the remaining arguments.

>>> repr(error)
"Exception('foobarbaz',)"

Eliminating the warning while still using .message

And the way you get rid of the DeprecationWarning is to subclass a builtin exception as the Python designers intended:

class MyException(Exception):

    def __init__(self, message, *args):
        self.message = message
        # delegate the rest of initialization to parent
        super(MyException, self).__init__(message, *args)

>>> myexception = MyException('my message')
>>> myexception.message
'my message'
>>> str(myexception)
'my message'
>>> repr(myexception)
"MyException('my message',)"

getting just the .message attribute without error.message

If you know there was one argument, a message, to the Exception and that’s what you want, it is preferable to avoid the message attribute and just take the str of the error. Say for a subclassed Exception:

class MyException(Exception):
    '''demo straight subclass'''

And usage:

>>> myexception = MyException('my message')
>>> str(myexception)
'my message'

See also this answer:

Proper way to declare custom exceptions in modern Python?


回答 4

据我所知,仅对message属性使用其他名称可以避免与基类发生冲突,从而停止弃用警告:

class MyException(Exception):

def __init__(self, message):
    self.msg = message

def __str__(self):
    return repr(self.msg)

在我看来就像是骇客。

也许有人可以解释为什么即使子类显式定义了message属性,也会发出警告。如果基类不再具有此属性,则应该没有问题。

As far as I can tell, simply using a different name for the message attribute avoids the conflict with the base class, and thus stops the deprecation warning:

class MyException(Exception):

def __init__(self, message):
    self.msg = message

def __str__(self):
    return repr(self.msg)

Seems like a hack to me.

Maybe someone can explain why the warning is issued even when the subclass defines a message attribute explicitly. If the base class no longer has this attribute, there shouldn’t be a problem.


回答 5

继续从geekQ的答案开始,首选的代码替换取决于您需要执行的操作:

### Problem
class MyException(Exception):
    """My documentation"""

try:
    raise MyException('my detailed description')
except MyException as my:
    ### Solution 1, fails in Python 2.x if MyException contains 🔥
    # with UnicodeEncodeError: 'ascii' codec can't encode characters in position 24-25: ordinal not in range(128)
    print(my)  # outputs 'my detailed description'

### Solution 2
# Works in Python 2.x if exception only has ASCII characters,
# should always work in Python 3.x
str(my)

### Solution 3
# Required in Python 2.x if you need to handle non-ASCII characters,
# such as δσφφδσ (as pointed out by jjc) or emoji 🔥 💕 🎁 💯 🌹
# but does not work in Python 3.x
unicode(my)

有时,异常包含多个参数,因此my.args[0]不能保证提供所有相关信息。

例如:

# Python 2.7
try:
    u'\u12345'.encode('utf-8').encode('utf-8')
except UnicodeDecodeError as e:
    print e.args[0]
    print e.args
    print str(e)

打印为输出:

ascii
('ascii', '\xe1\x88\xb45', 0, 1, 'ordinal not in range(128)')
'ascii' codec can't decode byte 0xe1 in position 0: ordinal not in range(128)

但是,这是上下文相关的折衷,因为例如:

# Python 2.7
>>> str(SyntaxError())
'None'
# 'None' compares True which might not be expected

Continuing on from geekQ’s answer, the preferred code replacement depends on what you need to do:

### Problem
class MyException(Exception):
    """My documentation"""

try:
    raise MyException('my detailed description')
except MyException as my:
    ### Solution 1, fails in Python 2.x if MyException contains 🔥
    # with UnicodeEncodeError: 'ascii' codec can't encode characters in position 24-25: ordinal not in range(128)
    print(my)  # outputs 'my detailed description'

### Solution 2
# Works in Python 2.x if exception only has ASCII characters,
# should always work in Python 3.x
str(my)

### Solution 3
# Required in Python 2.x if you need to handle non-ASCII characters,
# such as δσφφδσ (as pointed out by jjc) or emoji 🔥 💕 🎁 💯 🌹
# but does not work in Python 3.x
unicode(my)

Sometimes exceptions have more than one argument, so my.args[0] is not guaranteed to provide all the relevant information.

For instance:

# Python 2.7
try:
    u'\u12345'.encode('utf-8').encode('utf-8')
except UnicodeDecodeError as e:
    print e.args[0]
    print e.args
    print str(e)

Prints as output:

ascii
('ascii', '\xe1\x88\xb45', 0, 1, 'ordinal not in range(128)')
'ascii' codec can't decode byte 0xe1 in position 0: ordinal not in range(128)

However it’s a context sensitive trade off, because for instance:

# Python 2.7
>>> str(SyntaxError())
'None'
# 'None' compares True which might not be expected

回答 6

使用str(myexception)的建议会导致python 2.7中的unicode问题,例如:

str(Exception(u'δσφφδσ'))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-5: ordinal not in range(128)

:(

unicode(Exception(u'δσφφδσ')) 

可以按预期工作,并且在错误字符串的某些内容包括用户输入的情况下更可取

The advice to use str(myexception) leads to unicode problems in python 2.7, e.g.:

str(Exception(u'δσφφδσ'))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-5: ordinal not in range(128)

:(

unicode(Exception(u'δσφφδσ')) 

works as expected, and is preferred in cases where some of the content of the error string includes user input


回答 7

pzrq的帖子说使用:

str(e)

这正是我所需要的。

(如果您在unicode环境中,则似乎:

unicode(e)

可以正常工作,并且在非Unicode环境中似乎可以正常工作)

Pzrq说了很多其他好东西,但是由于所有好东西,我几乎都错过了他们的答案。由于我没有50分,因此我无法就他们的答案发表评论,以引起人们对有效的简单解决方案的关注;由于我没有15分,因此我无法投票赞成该答案,但是我可以发表评论(感觉是倒退的,但是哦,好)-我在这里发布-可能会因此而失去积分…

由于我的意思是要引起人们对pzrq答案的关注,请不要着迷并在下面的所有内容中忽略它。这篇文章的前几行是最重要的。

我的故事:

我来到这里的问题是,如果您想从无法控制的类中捕获异常,那么该怎么办?我当然不会继承我的代码使用的所有可能的类,以试图从所有可能的异常中获取消息!

我正在使用:

except Exception as e:
   print '%s (%s)' % (e.message,type(e))

正如我们现在所知道的那样,它给出了警告OP的警告(这将我带到了这里),而这就是pzrq给出的一种解决方法:

except Exception as e:
   print '%s (%s)' % (str(e),type(e))

没有。

我不是在unicode环境中,但是jjc的回答让我感到疑惑,因此我不得不尝试一下。在这种情况下,它将变为:

except Exception as e:
   print '%s (%s)' % (unicode(e),type(e))

令我惊讶的是,它的工作原理与str(e)完全一样-所以现在这就是我正在使用的。

不知道’str(e)/ unicode(e)’是否是’认可的Python方式’,我很可能会发现为什么当我达到3.0时这不好,但是有人希望能够处理不会死的意外异常(*)永远不会消失…

(*)嗯。“意外异常”-我想我口吃了!

pzrq’s post says to use:

str(e)

This was exactly what I needed.

(If you are in a unicode environment, it appears that:

unicode(e)

will work, and it appears to work fine in a non-unicode environment)

Pzrq said a lot of other good stuff, but I almost missed their answer due to all the good stuff. Since I don’t have 50 points I cannot comment on their answer to attempt to draw attention to the simple solution that works, and since I don’t have 15 I cannot vote that answer up, but I can post (feels backward, but oh well) – so here I am posting – probably lose points for that…

Since my point is to draw attention to pzrq’s answer, please don’t glaze over and miss it in all the below. the first few lines of this post are the most important.

My story:

The problem I came here for was if you want to catch an exception from a class that you have no control over – what then??? I’m certainly not going to subclass all possible classes my code uses in an attempt to be able to get a message out of all possible exceptions!

I was using:

except Exception as e:
   print '%s (%s)' % (e.message,type(e))

which, as we all now know, gives the warning OP asked about (which brought me here), and this, which pzrq gives as a way to do it:

except Exception as e:
   print '%s (%s)' % (str(e),type(e))

did not.

I’m not in a unicode environment, but jjc’s answer made me wonder, so I had to try it. In this context this becomes:

except Exception as e:
   print '%s (%s)' % (unicode(e),type(e))

which, to my surprise, worked exactly like str(e) – so now that’s what I’m using.

Don’t know if ‘str(e)/unicode(e)’ is the ‘approved Python way’, and I’ll probably find out why that’s not good when I get to 3.0, but one hopes that the ability to handle an unexpected exception (*) without dying and still get some information from it won’t ever go away…

(*) Hmm. “unexpected exception” – I think I just stuttered!