2011-08-18 12 views
20

Po pierwsze, nie jestem pewien, czy moje podejście jest właściwe, więc jestem otwarty na różne sugestie.Często powtarzana próba/z wyjątkiem Python

Jeśli instrukcje try/except są często powtarzane w kodzie?

try: 
    # Do similar thing 
    os.remove('/my/file') 
except OSError, e: 
    # Same exception handing 
    pass 

try: 
    # Do similar thing 
    os.chmod('/other/file', 0700) 
except OSError, e: 
    #Same exception handling 
    pass 

Na przykład za działania jednej linii można zdefiniować obsługi opakowanie wyjątku, a następnie przekazać funkcję lambda:

def may_exist(func): 
    "Work with file which you are not sure if exists.""" 
    try: 
     func() 
    except OSError, e: 
     # Same exception handling 
     pass 

may_exist(lambda: os.remove('/my/file')) 
may_exist(lambda: os.chmod('/other/file', 0700)) 

Czy to „rozwiązanie” po prostu zrobić rzeczy mniej oczywiste? Czy powinienem w pełni napisać wszystkie instrukcje try/except?

+0

możliwe duplikat [Python: Try-chyba jako wyrażenie] (http://stackoverflow.com/questions/7088009/python-try-except-as -an-expression) – agf

+0

Me and @kindall właśnie wczoraj odpowiedziały na to pytanie bardzo ładnie. – agf

+0

@agf: To pytanie wydaje się częściowo powiązane, dzięki za linkowanie. Jednak odpowiedź Neda Batcheldera ma tę zaletę, że nie ma potrzeby tworzenia funkcji poza blokiem kodu, dla którego wyjątki muszą zostać przechwycone. – sutre

Odpowiedz

24

Najlepszym sposobem abstrakcyjnego obsługi wyjątków jest z menedżerem kontekstu:

from contextlib import contextmanager 
@contextmanager 
def common_handling(): 
    try: 
     yield 
    finally: 
     # whatever your common handling is 

następnie:

with common_handling(): 
    os.remove('/my/file') 

with common_handling(): 
    os.chmod('/other/file', 0700) 

ma to, że zaletą tego, że możesz umieścić pełne instrukcje i więcej niż jeden z nich w każdym wspólnym bloku obsługi.

Należy pamiętać, że konieczność ciągłego korzystania z tej samej obsługi sprawia wrażenie wyjątków, które powodują nadmierną obsługę. Czy na pewno potrzebujesz tak wiele?

+0

Myślę, że dokładnie to, czego szukałem, ale mogę być ponad obsługi wyjątków. W takich przypadkach chcę pracować z plikami tylko wtedy, gdy istnieją. Mogę sprawdzić, czy istnieją wcześniej (os.path.filexists), ale z tego co rozumiem, to lepiej spróbować złapać wyjątki w python? – sutre

+0

W takim przypadku może być użyteczne przechwycenie * pierwszego * wyjątku, a następnie pominięcie całego bloku instrukcji dotyczących tego pliku, jeśli nie istnieje, ale niech wszystkie inne wyjątki z pozostałych operacji będą propagować, ponieważ mało prawdopodobne, że brak wyjątku w pierwszym, po którym następuje wyjątek w drugim, jest równoważny istnieniu pliku. – SingleNegationElimination

+0

@TokenMacGuy: Dzięki, to ma wiele sensu. Przyjrzę się, jak najlepiej to zrobić. – sutre

2

Myślę, że twoje ogólne rozwiązanie jest w porządku, ale nie użyłbym tych lambd na dole. Ja polecam przechodzenia z funkcji i argumenty jak ten

def may_exist(func, *args): 
    "Work with file which you are not sure if exists.""" 
    try: 
     func(args) 
    except OSError, e: 
     # Same exception handling 
     pass 

may_exist(os.remove, '/my/file') 
may_exist(os.chmod, '/other/file', '0700') 
4

Prawdopodobnie byłoby czystsze aby may_exist dekorator:

from functools import wraps 
def may_exist(func): 
    @wraps(func): 
    def wrapper(*args, **kwds): 
     try: 
      return func(*args, **kwds) 
     except OSError: 
      pass 
    return wrapper 

Następnie można albo zrobić:

may_exist(os.remove)('/my/file') 
may_exist(os.chmod)('/other/file', 0700) 

na wezwanie jednorazowej lub:

remove_if_exists = may_exist(os.remove) 
... 
remove_if_exists('somefile') 

jeśli używasz go dużo.

1

Byłoby coś w tej pracy:

def may_exist(func, *func_args): 
    try: 
     func(*func_args) 
    except OSError as e: 
     pass 
Powiązane problemy