chụp tin nhắn ngoại lệ python


520
import ftplib
import urllib2
import os
import logging
logger = logging.getLogger('ftpuploader')
hdlr = logging.FileHandler('ftplog.log')
formatter = logging.Formatter('%(asctime)s %(levelname)s %(message)s')
hdlr.setFormatter(formatter)
logger.addHandler(hdlr)
logger.setLevel(logging.INFO)
FTPADDR = "some ftp address"

def upload_to_ftp(con, filepath):
    try:
        f = open(filepath,'rb')                # file to send
        con.storbinary('STOR '+ filepath, f)         # Send the file
        f.close()                                # Close file and FTP
        logger.info('File successfully uploaded to '+ FTPADDR)
    except, e:
        logger.error('Failed to upload to ftp: '+ str(e))

Điều này dường như không hoạt động, tôi gặp lỗi cú pháp, cách làm việc này để ghi nhật ký tất cả các loại ngoại lệ vào một tệp là gì


2
Lõm của bạn bị hỏng. Và bỏ qua ,sau except.
Sven Marnach

3
@SvenMarnach, nếu bạn bỏ qua phần ,sau except, bạn sẽ nhận được global name 'e' is not defined, điều này không tốt hơn nhiều so với cú pháp sai.
Val

12
@Val: Nên except Exception as ehoặc except Exception, e, tùy thuộc vào phiên bản Python.
Sven Marnach

1
Có lẽ nó nằm ở đâu đó xung quanh 8 câu trả lời đó, nhưng khi bạn mở một tệp, phần đóng không bao giờ được nằm trong câu lệnh thử, mà là trong câu lệnh cuối cùng hoặc được bao bọc bởi câu lệnh.
JC Rocamonde

Câu trả lời:


733

Bạn phải xác định loại ngoại lệ nào bạn muốn bắt. Vì vậy, viết except Exception, e:thay vì except, e:cho một ngoại lệ chung (dù sao cũng sẽ được ghi lại).

Khả năng khác là viết toàn bộ thử / ngoại trừ mã theo cách này:

try:
    with open(filepath,'rb') as f:
        con.storbinary('STOR '+ filepath, f)
    logger.info('File successfully uploaded to '+ FTPADDR)
except Exception, e: # work on python 2.x
    logger.error('Failed to upload to ftp: '+ str(e))

trong Python 3.x và các phiên bản hiện đại của Python 2.x sử dụng except Exception as ethay vì except Exception, e:

try:
    with open(filepath,'rb') as f:
        con.storbinary('STOR '+ filepath, f)
    logger.info('File successfully uploaded to '+ FTPADDR)
except Exception as e: # work on python 3.x
    logger.error('Failed to upload to ftp: '+ str(e))

118
repr (e) cung cấp cho bạn ngoại lệ (và chuỗi thông báo); str (e) chỉ đưa ra chuỗi thông báo.
ngựa trắng

11
Thay thế cho đăng nhập ngoại lệ, bạn có thể sử dụng logger.exception(e)thay thế. Nó sẽ ghi lại ngoại lệ với trac trở lại ở cùng logging.ERRORcấp độ.
mbdevpl

1
@mbdevpl điều này dường như không đúng. Nó xuất hiện để gọi str () ngoại lệ: ideone.com/OaCOpO
KevinOrr

6
except Exception, e:ném lỗi Syntax cho tôi trong python 3. Điều này có được mong đợi không?
Charlie Parker

27
@CharlieParker trong Python3 viếtexcept Exception as e:
eumiro

282

Cú pháp không còn được hỗ trợ trong python 3. Thay vào đó hãy sử dụng cách sau.

try:
    do_something()
except BaseException as e:
    logger.error('Failed to do something: ' + str(e))

2
Trên thực tế, bạn nên sử dụng logger.error ('Không thể thực hiện điều gì đó:% s', str (e)) Theo cách đó, nếu mức logger của bạn vượt quá lỗi thì nó không thực hiện phép nội suy chuỗi.
avyfain

7
@ lượn sóng - Bạn không chính xác. Câu lệnh logging.error('foo %s', str(e))sẽ luôn chuyển đổi ethành một chuỗi. Để đạt được những gì bạn đang sử dụng, bạn sẽ sử dụng logging.error('foo %s', e)- do đó cho phép khung đăng nhập thực hiện (hoặc không thực hiện) chuyển đổi.
Ron Dahlgren

1
Bạn có thể xác minh trong REPL python (ở đây với Python 3.5.2 và ipython): xem ý chính của tôi ở đây
Ron Dahlgren

2
Thay thế cho đăng nhập ngoại lệ, bạn có thể sử dụng logger.exception(e)thay thế. Nó sẽ ghi lại ngoại lệ với trac trở lại ở cùng logging.ERRORcấp độ.
mbdevpl

11
Coi chừng đó except BaseExceptionexcept Exceptionkhông cùng cấp. except Exceptionkhông hoạt động trong Python3, nhưng nó sẽ không bắt được KeyboardInterruptví dụ (có thể rất thuận tiện nếu bạn muốn có thể làm gián đoạn mã của mình!), trong khi BaseExceptionbắt được bất kỳ ngoại lệ nào. Xem liên kết này để phân cấp các trường hợp ngoại lệ.
jeannej

41

Cập nhật điều này thành một cái gì đó đơn giản hơn cho logger (hoạt động cho cả python 2 và 3). Bạn không cần mô-đun trac trở lại.

import logging

logger = logging.Logger('catch_all')

def catchEverythingInLog():
    try:
        ... do something ...
    except Exception as e:
        logger.error(e, exc_info=True)
        ... exception handling ...

Bây giờ đây là cách cũ (mặc dù vẫn hoạt động):

import sys, traceback

def catchEverything():
    try:
        ... some operation(s) ...
    except:
        exc_type, exc_value, exc_traceback = sys.exc_info()
        ... exception handling ...

exc_value là thông báo lỗi.


2
Đây sẽ là phương pháp ưa thích của tôi. Tôi chỉ cần in chuỗi là hữu ích để đăng nhập, nhưng nếu tôi cần làm bất cứ điều gì với thông tin đó, tôi cần nhiều hơn là một chuỗi.
sulimmesh

3
Bạn không cần phải 'nhập dấu vết' trong ví dụ thứ hai, phải không?
starikoff

34

Có một số trường hợp bạn có thể sử dụng e.message hoặc e.messages .. Nhưng nó không hoạt động trong mọi trường hợp. Dù sao, an toàn hơn là sử dụng str (e)

try:
  ...
except Exception as e:
  print(e.message)

42
Vấn đề ở đây là, ví dụ, nếu bạn except Exception as e, và elà một IOError, bạn sẽ có được e.errno, e.filenamee.strerror, nhưng dường như không có e.message(ít nhất là trong Python 2.7.12). Nếu bạn muốn chụp thông báo lỗi, hãy sử dụng str(e), như trong các câu trả lời khác.
thư tín

@epalm Nếu bạn bắt IOError trước Ngoại lệ thì sao?
Albert Thompson

@ HeribertoJuárez Tại sao bắt các trường hợp đặc biệt trong khi bạn chỉ có thể chuyển nó thành chuỗi?
HosseyNJF

25

Nếu bạn muốn lớp lỗi, thông báo lỗi và theo dõi ngăn xếp (hoặc một vài trong số đó), hãy sử dụng sys.exec_info().

Mã làm việc tối thiểu với một số định dạng:

import sys
import traceback

try:
    ans = 1/0
except BaseException as ex:
    # Get current system exception
    ex_type, ex_value, ex_traceback = sys.exc_info()

    # Extract unformatter stack traces as tuples
    trace_back = traceback.extract_tb(ex_traceback)

    # Format stacktrace
    stack_trace = list()

    for trace in trace_back:
        stack_trace.append("File : %s , Line : %d, Func.Name : %s, Message : %s" % (trace[0], trace[1], trace[2], trace[3]))

    print("Exception type : %s " % ex_type.__name__)
    print("Exception message : %s" %ex_value)
    print("Stack trace : %s" %stack_trace)

Cung cấp đầu ra sau:

Exception type : ZeroDivisionError
Exception message : division by zero
Stack trace : ['File : .\\test.py , Line : 5, Func.Name : <module>, Message : ans = 1/0']

Hàm sys.exc_info () cung cấp cho bạn chi tiết về ngoại lệ gần đây nhất. Nó trả về một tuple của (type, value, traceback).

tracebacklà một ví dụ của đối tượng truy nguyên. Bạn có thể định dạng theo dõi với các phương pháp được cung cấp. Nhiều hơn có thể được tìm thấy trong các tài liệu trac trở lại .


3
Sử dụng e.__class__.__name__ có thể trả về lớp ngoại lệ là tốt.
kenorb

19

Bạn có thể sử dụng logger.exception("msg")để đăng nhập ngoại lệ với truy nguyên:

try:
    #your code
except Exception as e:
    logger.exception('Failed: ' + str(e))

Thật trùng hợp, e.msglà đại diện chuỗi của Exceptionlớp.
MarkHu

5
Hoặc đơn giản logger.exception(e).
mbdevpl


5

Bạn có thể thử chỉ định loại BaseException một cách rõ ràng. Tuy nhiên, điều này sẽ chỉ bắt các dẫn xuất của BaseException. Trong khi điều này bao gồm tất cả các trường hợp ngoại lệ do triển khai thực hiện, nó cũng có thể nâng cao các lớp kiểu cũ tùy ý.

try:
  do_something()
except BaseException, e:
  logger.error('Failed to do something: ' + str(e))

4

Sử dụng str (ex) để in thực thi

try:
   #your code
except ex:
   print(str(ex))

2

đối với những người đấu tranh trong tương lai, trong python 3.8.2 (và có thể một vài phiên bản trước đó), cú pháp là

except Attribute as e:
    print(e)

1

Sử dụng str(e)hoặc repr(e)để thể hiện ngoại lệ, bạn sẽ không nhận được dấu vết ngăn xếp thực tế, vì vậy sẽ không hữu ích khi tìm thấy ngoại lệ đó ở đâu.

Sau khi đọc các câu trả lời khác và tài liệu gói ghi nhật ký, hai cách sau đây rất hữu ích để in theo dõi ngăn xếp thực tế để gỡ lỗi dễ dàng hơn:

sử dụng logger.debug()với tham sốexc_info

try:
    # my code
exception SomeError as e:
    logger.debug(e, exc_info=True)

sử dụng logger.exception()

hoặc chúng ta có thể trực tiếp sử dụng logger.exception()để in ngoại lệ.

try:
    # my code
exception SomeError as e:
    logger.exception(e)
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.