python istisna mesajı yakalama


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

Bu işe yaramaz gibi görünüyor, sözdizimi hatası alıyorum, bir dosyaya her türlü özel durumu günlüğe kaydetmek için bunu yapmanın uygun yolu nedir


2
Girintiniz kırıldı. Ve ,sonradan atlayın except.
Sven Marnach

3
Eğer ihmal varsa @SvenMarnach, ,SONRA exceptelde edersiniz global name 'e' is not definedçok daha iyi yanlış sözdizimi daha olmadığı.
Val

12
@Val: Python sürümüne bağlı olarak except Exception as eveya olmalıdır except Exception, e.
Sven Marnach

1
Muhtemelen bu 8 cevabın etrafında bir yerdedir, ancak bir dosyayı açtığınızda yakın kısım asla try ifadesinin içinde olmamalıdır, ancak nihayet bir ifadede veya bir with ifadesiyle sarılmalıdır.
JC Rocamonde

Yanıtlar:


733

Hangi tür istisnaları yakalamak istediğinizi tanımlamanız gerekir. Genel bir istisna except Exception, e:yerine yazın except, e:(yine de kaydedilecektir).

Diğer olasılık, tüm deneme / kodunuzu şu şekilde yazmanızdır:

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

Python 3.x'te ve Python 2.x'in modern sürümlerinde şunlar except Exception as eyerine kullanın 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) size istisna (ve mesaj dizesi) verir; str (e) yalnızca mesaj dizesini verir.
Beyazsakal

11
Günlüğe kaydetme istisnasına alternatif olarak kullanabilirsiniz logger.exception(e). İstisna aynı logging.ERRORdüzeyde geri izleme ile günlüğe kaydedilir .
mbdevpl

1
@mbdevpl bu doğru görünmüyor. İstisnada
KevinOrr

6
except Exception, e:Python 3'te bana bir sözdizimi hatası veriyor. Bu bekleniyor mu?
Charlie Parker

27
@CharlieParker in Python3 writeexcept Exception as e:
eumiro 01

282

Sözdizimi artık python 3'te desteklenmemektedir. Bunun yerine aşağıdakileri kullanın.

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

2
Aslında logger.error ('Bir şey yapılamadı:% s', str (e)) kullanmalısınız. Bu şekilde, günlükçü düzeyiniz hatanın üstündeyse dize enterpolasyonu yapmaz.
avyfain

7
@avyfain - Yanılıyorsunuz. İfade logging.error('foo %s', str(e))her zaman ebir dizeye dönüştürülür . Sonuçta ne elde etmek için kullanacağınız logging.error('foo %s', e)- böylece kayıt çerçevesinin dönüşüm yapmasına (veya yapmamasına) izin verirsiniz .
Ron Dahlgren

1
Bir python REPL'de (burada Python 3.5.2 ve ipython ile) doğrulayabilirsiniz: özümü buradan görebilirsiniz
Ron Dahlgren

2
Günlüğe kaydetme istisnasına alternatif olarak kullanabilirsiniz logger.exception(e). İstisna aynı logging.ERRORdüzeyde geri izleme ile günlüğe kaydedilir .
mbdevpl

11
Buna dikkat edin except BaseExceptionve except Exceptionaynı seviyede değilsiniz. except ExceptionPython3'te çalışır, ancak KeyboardInterruptörneğin (kodunuzu kesintiye uğratmak istiyorsanız çok uygun olabilir!) Ancak, BaseExceptionherhangi bir istisna yakalar. İstisnalar hiyerarşisi için bu bağlantıya bakın .
jeannej

41

Bunu logger için daha basit bir şeye güncelleme (hem python 2 hem de 3 için çalışır). Geri izleme modülüne ihtiyacınız yoktur.

import logging

logger = logging.Logger('catch_all')

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

Bu şimdi eski yöntem (yine de çalışıyor):

import sys, traceback

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

exc_value, hata iletisidir.


2
Bu benim tercih ettiğim yöntem. Sadece dize yazdırmak sanırım günlüğe kaydetmek için yararlıdır, ama bu bilgi ile bir şey yapmak gerekirse ben sadece bir dize daha gerekir.
sulimmesh

3
İkinci örnekte 'geri izleme' aktarmanıza gerek yok, değil mi?
starikoff

34

E.message veya e.message kullanabileceğiniz bazı durumlar vardır . Ancak her durumda çalışmaz. Her neyse, daha güvenli olan str (e) ' yi kullanmaktır.

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

42
Bu sorun eğer, örneğin, bir except Exception as eve ebir olduğunu IOError, almak e.errno, e.filenameve e.strerror, ancak görünüşe göre hiçbir e.message(Python en az 2.7.12). Hata mesajını yakalamak istiyorsanız str(e), diğer yanıtlarda olduğu gibi kullanın .
epalm

@ epalm İstisnadan önce IOError'u yakalarsanız ne olur?
Albert Thompson

@ HeribertoJuárez Neden sadece özel durumları yakalayabilirsin?
HosseyNJF

25

Hata sınıfını, hata mesajını ve yığın izlemesini (veya bunlardan bazılarını) istiyorsanız kullanın sys.exec_info().

Bazı biçimlendirmelerle minimum çalışma kodu:

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)

Hangi aşağıdaki çıktıyı verir:

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

Sys.exc_info () işlevi size en son istisna hakkında ayrıntılı bilgi verir. Bir demet döndürür (type, value, traceback).

tracebackgeri izleme nesnesinin bir örneğidir. İzlemeyi sağlanan yöntemlerle biçimlendirebilirsiniz. Geri izleme belgelerinde daha fazla bilgi bulunabilir .


3
Kullanmak e.__class__.__name__ da istisna sınıfını döndürebilir.
kenorb

19

Geri logger.exception("msg")izleme özelliğiyle günlüğe kaydetme istisnası için kullanabilirsiniz:

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

Tesadüfen, sınıfın e.msgdize temsilidir Exception.
MarkHu

5
Veya basitçe logger.exception(e).
mbdevpl


5

BaseException türünü açıkça belirtmeyi deneyebilirsiniz. Ancak, bu yalnızca BaseException türevlerini yakalar. Bu, uygulama tarafından sağlanan tüm istisnaları içermekle birlikte, muhtemelen keyfi eski stil sınıflarını yükseltmektir.

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


2

gelecekteki mücadeleciler için, python 3.8.2'de (ve belki de bundan önceki birkaç sürümde), sözdizimi

except Attribute as e:
    print(e)

1

İstisnayı temsil etmek için str(e)veya öğesini kullanmak repr(e), gerçek yığın izini alamazsınız, bu nedenle istisnanın nerede olduğunu bulmak yararlı değildir.

Diğer yanıtları ve günlük paketi paket belgesini okuduktan sonra, aşağıdaki iki yol daha kolay hata ayıklama için gerçek yığın izini yazdırmak için harika çalışır:

Kullanım logger.debug()parametresiyleexc_info

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

kullanım logger.exception()

veya doğrudan logger.exception()istisnayı yazdırmak için kullanabiliriz .

try:
    # my code
exception SomeError as e:
    logger.exception(e)
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.