Cara menggunakan value error in python

Saya memiliki blok try ini dalam kode saya:

try:
    do_something_that_might_raise_an_exception()
except ValueError as err:
    errmsg = 'My custom error message.'
    raise ValueError(errmsg)

Sebenarnya, saya sebenarnya menaikkan lainnyaValueError, bukan ValueError yang dilemparkan oleh do_something...(), yang disebut sebagai err dalam kasus ini. Bagaimana cara saya melampirkan pesan khusus ke err? Saya mencoba kode berikut tetapi gagal karena err, contoh ValueError, tidak dapat dipanggil:

try:
    do_something_that_might_raise_an_exception()
except ValueError as err:
    errmsg = 'My custom error message.'
    raise err(errmsg)

Pembaruan: Untuk Python 3, centang Jawaban Ben


Untuk melampirkan pesan ke pengecualian saat ini dan menaikkannya kembali: (Coba luar/hanya untuk menunjukkan efeknya)

Untuk python 2.x di mana x> = 6:

try:
    try:
      raise ValueError  # something bad...
    except ValueError as err:
      err.message=err.message+" hello"
      raise              # re-raise current exception
except ValueError as e:
    print(" got error of type "+ str(type(e))+" with message " +e.message)

Ini juga akan melakukan hal yang benar jika err adalah diturunkan dari ValueError. Misalnya UnicodeDecodeError

Perhatikan bahwa Anda dapat menambahkan apa pun yang Anda suka ke err. Misalnya err.problematic_array=[1,2,3].


Edit: @Ducan menunjuk dalam komentar di atas tidak bekerja dengan python 3 karena .message bukan anggota ValueError Sebagai gantinya, Anda dapat menggunakan ini (python valid 2.6 atau yang lebih baru atau 3.x):

try:
    try:
      raise ValueError
    except ValueError as err:
       if not err.args: 
           err.args=('',)
       err.args = err.args + ("hello",)
       raise 
except ValueError as e:
    print(" error was "+ str(type(e))+str(e.args))

Edit2:

Bergantung pada apa tujuannya, Anda juga dapat memilih untuk menambahkan informasi tambahan di bawah nama variabel Anda sendiri. Untuk python2 dan python3:

try:
    try:
      raise ValueError
    except ValueError as err:
       err.extra_info = "hello"
       raise 
except ValueError as e:
    print(" error was "+ str(type(e))+str(e))
    if 'extra_info' in dir(e):
       print e.extra_info

Saya menyadari pertanyaan ini telah ada untuk sementara waktu, tetapi begitu Anda cukup beruntung hanya mendukung python 3.x, ini benar-benar menjadi sesuatu yang indah :)

bangkit dari

Kami dapat membuat rantai pengecualian menggunakan meningkatkan dari .

try:
    1 / 0
except ZeroDivisionError as e:
    raise Exception('Smelly socks') from e

Dalam hal ini, pengecualian yang akan ditangkap oleh penelepon Anda memiliki nomor baris tempat kami menaikkan pengecualian kami.

Traceback (most recent call last):
  File "test.py", line 2, in <module>
    1 / 0
ZeroDivisionError: division by zero

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "test.py", line 4, in <module>
    raise Exception('Smelly socks') from e
Exception: Smelly socks

Perhatikan pengecualian bawah hanya memiliki stacktrace dari tempat kami mengangkat pengecualian kami. Penelepon Anda masih bisa mendapatkan pengecualian asli dengan mengakses atribut __cause__ pengecualian yang mereka tangkap.

with_traceback

Atau Anda dapat menggunakan with_traceback .

try:
    1 / 0
except ZeroDivisionError as e:
    raise Exception('Smelly socks').with_traceback(e.__traceback__)

Menggunakan formulir ini, pengecualian penelepon Anda akan menangkap memiliki traceback dari tempat kesalahan asli terjadi.

Traceback (most recent call last):
  File "test.py", line 2, in <module>
    1 / 0
ZeroDivisionError: division by zero

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "test.py", line 4, in <module>
    raise Exception('Smelly socks').with_traceback(e.__traceback__)
  File "test.py", line 2, in <module>
    1 / 0
Exception: Smelly socks

Perhatikan bahwa pengecualian bawah memiliki garis tempat kami melakukan pembagian yang tidak valid serta garis tempat kami mengeluarkan pengecualian.

try:
    try:
        int('a')
    except ValueError as e:
        raise ValueError('There is a problem: {0}'.format(e))
except ValueError as err:
    print err

cetakan:

There is a problem: invalid literal for int() with base 10: 'a'

Tampaknya semua jawaban menambahkan info ke e.args [0], sehingga mengubah pesan kesalahan yang ada. Apakah ada kerugian untuk memperpanjang args Tuple? Saya pikir kemungkinan terbalik adalah, Anda dapat meninggalkan pesan kesalahan asli sendirian untuk kasus-kasus di mana parsing string itu diperlukan; dan Anda dapat menambahkan beberapa elemen ke Tuple jika penanganan kesalahan khusus Anda menghasilkan beberapa pesan atau kode kesalahan, untuk kasus-kasus di mana traceback akan diuraikan secara program (seperti melalui alat pemantauan sistem).

## Approach #1, if the exception may not be derived from Exception and well-behaved:

def to_int(x):
    try:
        return int(x)
    except Exception as e:
        e.args = (e.args if e.args else Tuple()) + ('Custom message',)
        raise

>>> to_int('12')
12

>>> to_int('12 monkeys')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 3, in to_int
ValueError: ("invalid literal for int() with base 10: '12 monkeys'", 'Custom message')

atau

## Approach #2, if the exception is always derived from Exception and well-behaved:

def to_int(x):
    try:
        return int(x)
    except Exception as e:
        e.args += ('Custom message',)
        raise

>>> to_int('12')
12

>>> to_int('12 monkeys')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 3, in to_int
ValueError: ("invalid literal for int() with base 10: '12 monkeys'", 'Custom message')

Bisakah Anda melihat kelemahan dari pendekatan ini?

Templat kode ini harus memungkinkan Anda untuk meningkatkan pengecualian dengan pesan khusus.

try:
     raise ValueError
except ValueError as err:
    raise type(err)("my message")

Ini adalah fungsi yang saya gunakan untuk mengubah pesan pengecualian di Python 2.7 dan 3.x sambil mempertahankan traceback asli. Membutuhkan six

def reraise_modify(caught_exc, append_msg, prepend=False):
    """Append message to exception while preserving attributes.

    Preserves exception class, and exception traceback.

    Note:
        This function needs to be called inside an except because
        `sys.exc_info()` requires the exception context.

    Args:
        caught_exc(Exception): The caught exception object
        append_msg(str): The message to append to the caught exception
        prepend(bool): If True prepend the message to args instead of appending

    Returns:
        None

    Side Effects:
        Re-raises the exception with the preserved data / trace but
        modified message
    """
    ExceptClass = type(caught_exc)
    # Keep old traceback
    traceback = sys.exc_info()[2]
    if not caught_exc.args:
        # If no args, create our own Tuple
        arg_list = [append_msg]
    else:
        # Take the last arg
        # If it is a string
        # append your message.
        # Otherwise append it to the
        # arg list(Not as pretty)
        arg_list = list(caught_exc.args[:-1])
        last_arg = caught_exc.args[-1]
        if isinstance(last_arg, str):
            if prepend:
                arg_list.append(append_msg + last_arg)
            else:
                arg_list.append(last_arg + append_msg)
        else:
            arg_list += [last_arg, append_msg]
    caught_exc.args = Tuple(arg_list)
    six.reraise(ExceptClass,
                caught_exc,
                traceback)

Entah menaikkan pengecualian baru dengan menggunakan pesan kesalahan Anda

raise Exception('your error message')

atau

raise ValueError('your error message')

di tempat Anda ingin meningkatkannya OR lampirkan (ganti) pesan kesalahan ke dalam pengecualian saat ini menggunakan 'from':

except ValueError as e:
  raise ValueError('your message') from e

Pengecualian bawaan Python 3 memiliki bidang strerror:

except ValueError as err:
  err.strerror = "New error message"
  raise err

Jawaban saat ini tidak berfungsi dengan baik untuk saya, jika pengecualian tidak ditangkap kembali pesan terlampir tidak ditampilkan.

Tetapi melakukan seperti di bawah keduanya menyimpan jejak dan menunjukkan pesan yang ditambahkan terlepas dari apakah pengecualian ditangkap kembali atau tidak.

try:
  raise ValueError("Original message")
except ValueError as err:
  t, v, tb = sys.exc_info()
  raise t, ValueError(err.message + " Appended Info"), tb

(Saya menggunakan Python 2.7, belum mencobanya dengan Python 3)