BaseException.message Python 2.6'da kullanımdan kaldırıldı


177

Aşağıdaki kullanıcı tanımlı özel durumu kullandığımda BaseException.message Python 2.6'da kullanımdan kaldırıldığına dair bir uyarı alıyorum:

class MyException(Exception):

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

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

Bu uyarı:

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

Bunun nesi var? Kullanımdan kaldırma uyarısından kurtulmak için neyi değiştirmek zorundayım?


9
Sebepler için PEP 352'ye
balpha

Yanıtlar:


154

Çözüm - neredeyse hiç kodlamaya gerek yok

İstisna sınıfınızı devralın Exceptionve mesajı ilk parametre olarak yapıcıya iletin

Misal:

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

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

Sen kullanabilirsiniz str(my)ya da (daha az zarif) my.args[0]özel bir ileti erişmek için.

Arka fon

Python'un (2.6'dan) daha yeni sürümlerinde, özel istisna sınıflarımızı ( Python 2.5'ten başlayarak ) BaseException'dan devralınan Exception'dan devralmamız gerekiyor . Arka plan PEP 352'de ayrıntılı olarak tarif edilmektedir .

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__ve __repr__özellikle tek bir argümanda (mesaj olarak kullanılabilir) zaten anlamlı bir şekilde uygulanmaktadır.

Sen tekrarlamak gerekmez __str__veya __init__uygulama veya oluşturma _get_messagebaşkaları tarafından önerildiği gibi.


5
@Matt tarafından önerilen BaseException'ı İstisna olarak değiştirdi
geekQ

8
strKural dışı durum bir unicode bağımsız değişkeniyle oluşturulmuşsa sonları kullanma : str(MyException(u'\xe5'))yükseltir UnicodeEncodeError. unicodeBunun yerine kullanmak , UnicodeDecodeError öğesini yükselttiği için strkusursuz değildir unicode(MyException('\xe5')). Bu, argümanın önceden olup olmadığını bilmiyorsam strveya daha önce kullandığım yeri unicodekullanmam gerektiği anlamına mı geliyor ? .args[0].message
kasperd

1
@kasperd Neredeyse tüm Python unicode sorunları gibi, bu bir unicode sandviç ile çözülebilir .
Ryan P

3
@RyanP İçinde neler olup bittiğini gerçekten kontrol ettiğimi varsayıyor. İşte karşılaştığım hayatın bir gerçeği. Birden fazla üçüncü taraf kütüphanesinden istisnaları ele almak zorundayım. Bunlardan bazıları istisnalarına unicode, bazıları ise str. Kütüphanelerden biri bile unicode'dan miras kalan kendi özel sınıfına sahiptir, ancak spesifikasyonun gerektirdiği şekilde str yerine unicode döndüren kendi repr yöntemine sahiptir.
kasperd

1
Ben btw yaptım. .messageProjemizdeki tüm kullanımları ile değiştirin .args[0]ve bu bizim için herhangi bir soruna yol açmadı.
kasperd

26

Evet, Python 2.6'da kullanımdan kaldırıldı, çünkü Python 3.0'da kullanımdan kaldırılıyor

BaseException sınıfı artık hata iletisini depolamanın bir yolunu sunmuyor. Bunu kendiniz uygulamak zorunda kalacaksınız. Bunu, iletiyi depolamak için bir özellik kullanan bir alt sınıfla yapabilirsiniz.

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

Bu yardımcı olur umarım


1
Yükseltme sırasında mesajı nasıl başlatırsınız? Kodu MyException ("bazı mesajlar") çağrılarak ayarlanan mesajı gösterdi
eric.frederich

Örneğimdeki yöntemler yalnızca message özelliğini uygulamak içindir. Özelliğin nasıl kullanıldığı kodlayıcıya bağlıdır. Bu durumda OP init ve str komutlarını kullanır , kodunda yayınladığı yöntemlerini .
Sahas

1
Yalnızca başka bir değişken okuyorsa, alıcı / ayarlayıcı yerine genel bir değişken kullanmayı düşünün. @propertyGerçekten kapsüllemeye ihtiyacınız olduğunda bunu daha sonra bir sözdizimine yükseltebilirsiniz .
vdboor

2
@vdboor: @propertykullanımdan kaldırma uyarısını devre dışı bırakmak için kullanıyor .
bukzor

Kontrollü ve değişmeyen değeri almak ve ayarlamak dışında hiçbir şey yapmayan özellikler oluşturmak, kuralsızdır ve işe yaramaz. Özelliklerin tamamı, bir alıcı veya bir ayarlayıcı gerçekten gerekli olana kadar, genel özellikleri serbestçe kullanmasına izin vermektir. Daha sonra, herhangi bir istemci kodunu kırmadan public niteliğini bir özelliğe dönüştürürsünüz.
Luciano Ramalho

9
class MyException(Exception):

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

e = MyException('asdf')
print e

Bu Python2.6 tarzında sınıfınız. Yeni istisna isteğe bağlı sayıda argüman almaktadır.


1
Eski İstisna sınıfı da herhangi bir sayıda argüman alır. Yaptığınız gibi message özelliğinden tamamen kaçınabilirsiniz, ancak bu mevcut kodunuzu bozarsa, kendi message özelliğinizi uygulayarak sorunu çözebilirsiniz.
Sahas

8

Uyarı nasıl çoğaltılır

Sorunu açıklığa kavuşturayım, biri sorunun örnek koduyla çoğaltılamadığından, uyarılar açıksa ( -Wbayrak , PYTHONWARNINGSortam değişkeni veya uyarı modülü aracılığıyla) Python 2.6 ve 2.7'deki uyarıyı çoğaltacaktır :

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

Kullanmayı bırak .message

repr(error)Hata türünün adını, varsa iletinin repr'sini ve kalan argümanların repr'ini içeren bir dize döndüren tercih ederim .

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

Hala kullanırken uyarıyı ortadan kaldırma .message

Ve olsun yolu kurtulmak ait DeprecationWarningPython tasarımcıları amaçlandığı gibi bir yerleşik istisna alt sınıfı için geçerli:

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',)"

.messageolmadan sadece niteliği elde etmekerror.message

İstisna için bir argüman, bir mesaj olduğunu biliyorsanız ve istediğiniz şey buysa, mesaj özelliğinden kaçınmak ve sadece strhatayı almak tercih edilir . Bir alt sınıf için söyle Exception:

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

Ve kullanım:

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

Ayrıca bu cevaba bakınız:

Modern Python'da özel istisnalar bildirmenin doğru yolu?


4

Anlayabildiğim kadarıyla, mesaj özniteliği için farklı bir ad kullanmak temel sınıfla çakışmayı önler ve böylece kullanımdan kaldırma uyarısını durdurur:

class MyException(Exception):

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

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

Bana bir hack gibi görünüyor.

Belki birisi, alt sınıf bir ileti niteliğini açıkça tanımlasa bile uyarının neden verildiğini açıklayabilir. Temel sınıf artık bu özniteliğe sahip değilse, bir sorun olmamalıdır.


4

GeekQ'nun cevabından devam ederek , tercih edilen kod değişimi ne yapmanız gerektiğine bağlıdır:

### 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)

Bazen istisnaların birden fazla argümanı olabilir, bu yüzden my.args[0] ilgili tüm bilgileri sağlaması garanti edilmez.

Örneğin:

# 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)

Çıktı olarak yazdırır:

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)

Ancak, bağlama duyarlı bir değiş tokuş, çünkü:

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

1
Evet, fazla düşünmeyin. Yerine str(my)kullanın my.message.
Christian Long

1

Str (myexception) kullanılması önerisi, python 2.7'de unicode sorunlarına yol açar, örneğin:

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'δσφφδσ')) 

beklendiği gibi çalışır ve hata dizesinin içeriğinin bir kısmının kullanıcı girdisi içerdiği durumlarda tercih edilir


1

pzrq adlı kullanıcının gönderisi şunları kullanıyor:

str(e)

Tam da ihtiyacım olan buydu.

(Unicode bir ortamdaysanız, şöyle görünür:

unicode(e)

ve unicode olmayan bir ortamda iyi çalışıyor gibi görünüyor)

Pzrq başka birçok iyi şey söyledi, ama neredeyse tüm iyi şeyler yüzünden cevaplarını kaçırdım. 50 puanım olmadığı için, işe yarayan basit çözüme dikkat çekmek için cevapları hakkında yorum yapamam ve 15 olmadığım için bu cevabı oylayamıyorum, ancak mesaj gönderebiliyorum (geri geliyor, ama oh iyi) - işte burada gönderiyorum - muhtemelen bunun için puan kaybedersiniz ...

Demek istediğim, pzrq'ın cevabına dikkat çekmek olduğundan, lütfen sır almayın ve aşağıdan kaçırmayın. bu yazının ilk birkaç satırı en önemlisidir.

Benim hikayem:

Buraya geldiğim sorun, üzerinde hiçbir kontrole sahip olmadığınız bir sınıftan bir istisna yakalamak istiyorsanız - ne o zaman ??? Kesinlikle tüm olası istisnalar dışında bir mesaj almak için bir girişimde benim kod kullandığı tüm olası sınıfları alt sınıf olmayacak!

Kullanıyordum:

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

hepimizin bildiği gibi, OP'nin (beni buraya getirdiğini) sorduğu uyarıyı verir ve bu, pzrq'in bunu yapmanın bir yolu olarak verir:

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

olmadı.

Unicode bir ortamda değilim, ama jjc'nin cevabı beni meraklandırdı, bu yüzden denemek zorundaydım. Bu bağlamda bu:

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

ki, sürpriz olarak, tam olarak str (e) gibi çalıştı - şimdi kullanıyorum.

'Str (e) / unicode (e)' nin 'onaylı Python yolu' olup olmadığını bilmiyorum ve muhtemelen 3.0'a geldiğimde bunun neden iyi olmadığını anlayacağım, ancak bir beklenmedik istisna (*) ölmeden ve hala ondan bazı bilgiler almak hiç gitmeyecek ...

(*) Hmm. "beklenmedik istisna" - Ben sadece kekeledi sanırım!

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.