#python #for-loop #exception
#python #для цикла #исключение
Вопрос:
Прошу прощения, если этот вопрос задавался ранее, но я не смог найти похожий вопрос и надеялся, что SO порекомендует мне его при вводе.
Сценарий: созданные вручную папки с вложенной папкой и файлами. На каждом уровне папок я хочу выполнить определенную функцию. Вместо того, чтобы вызывать исключение каждый раз при возникновении ошибки, я хотел бы распечатать их и продолжить цикл, чтобы в конце у меня был полный список ошибок.
Вот MWE, использующий упрощенные функции того, как выглядит мой код:
import os, stat
def folder_info(folder):
if len(folder) > 20:
raise Exception('Folder {} name too long'.format(folder))
print(folder)
subfolders = os.listdir(folder)
return len(folder), subfolders
raise_error = False
folders = [f for f in os.listdir() if os.path.isdir(f)]
for folder in folders:
try:
length, subfolders = folder_info(folder)
except Exception as error:
if raise_error: raise
print('Error: {}'.format(error))
continue
for subfolder in subfolders:
subfolder = os.path.join(folder, subfolder)
try:
length, subfolders = folder_info(subfolder)
except Exception as error:
if raise_error: raise
print('Error: {}'.format(error))
continue
В идеале я хотел бы что-то, где мне не нужно вводить оператор try
and except
для каждого вложенного цикла. На что я надеюсь:
for folder in folders:
arg1, arg2 = exceptionwrapper(myfunction1(folder), raise_error)
for subfolder in arg2:
subfolder = os.path.join(folder, subfolder)
arg1, arg2, arg3 = exceptionwrapper(myfunction2(subfolder), raise_error)
for subsubfolder in arg3:
arg1, arg2 = exceptionwrapper(myfunction3(subsubfolders), raise_error)
Я пробовал следующие решения с функциями декоратора, но я не смог передать continue
или выяснить, куда это должно идти. Это моя лучшая попытка, и при попытке передать у меня синтаксическая ошибка continue
:
def exceptionwrapper(function, raise_error, after_error: function = continue):
def decorator(func):
def new_func(*args, **kwargs):
try:
return func(*args, **kwargs)
except Exception as error:
if raise_error: raise
print('Error: {}'.format(error))
return after_error
return new_func
return decorator
Любая помощь была бы оценена!
Ответ №1:
Весь ваш код можно Pythonic
записать в несколько строк, если бы вы могли использовать os.walk.
import os
for root, folders, files in os.walk(os.getcwd()):
for folder in folders:
print('dir is: ', folder)
try:
if len(folder) > 20:
raise Exception('Folder {} name too long'.format(folder))
except Exception as error_message:
print('Error in folder: {} due to: {}'.format(folder, error_message))
Как вы указали на другом уровне папки, вам нужно вызывать разные функции, вы можете попробовать, как показано ниже:
import os
curr_folder = os.getcwd()
for root, folders, files in os.walk(curr_folder):
for folder in folders:
print('dir is: ', folder)
folder_level = root[len(curr_folder) 1:].count(os.sep)
print('level is: ', folder_level)
if folder_level == 0:
# call myfunction0
pass
elif folder_level == 1:
# call myfunction1
pass
elif folder_level == 2:
# call myfunction2
pass
Комментарии:
1. Спасибо за предложение. К сожалению, приведенный мной пример, возможно, был слишком упрощен. На разных уровнях вложенных папок я использую разные функции (
myfunction1
,myfunction2
и т.д. как в моем идеальном блоке кода), поэтомуos.walk
в этом случае не сработало бы.