【问题标题】:Overpass a custom exception but print all the other exceptions超越自定义异常但打印所有其他异常
【发布时间】:2020-05-21 13:20:43
【问题描述】:

我正在运行以下 try-except 代码:

try:
    paths = file_system_client.get_paths("{0}/{1}/0/{2}/{3}/{4}".format(container_initial_folder, container_second_folder, chronological_date[0], chronological_date[1], chronological_date[2]), recursive=True)
    list_of_paths=["abfss://{0}@{1}.dfs.core.windows.net/".format(storage_container_name, storage_account_name)+path.name for path in paths if ".avro" in path.name]

except Exception as e:
    if e=="AccountIsDisabled":
        pass
    else:
        print(e)

如果我的 try-except 发生在它上面,我既不想打印以下错误,也不想在遇到这个错误时停止我的程序执行:

"(AccountIsDisabled) The specified account is disabled.
RequestId:3159a59e-d01f-0091-5f71-2ff884000000
Time:2020-05-21T13:09:03.3540242Z"

我只想overpass它并打印任何其他将发生的错误/异常(例如 TypeError、ValueError 等)。

这在 Python 3 中可行吗?

请注意,.get_paths() 方法属于 azure.storage.filedatalake 模块,该模块可以将 Python 与 Azure Data Lake 直接连接以进行路径提取。

我在注释中指出我试图绕过的异常不是内置异常。


[更新]按照建议的附加答案进行排序后,我将代码修改为:

import sys
from concurrent.futures import ThreadPoolExecutor
from azure.storage.filedatalake._models import StorageErrorException
from azure.storage.filedatalake import DataLakeServiceClient, DataLakeFileClient

storage_container_name="name1" #confidential
storage_account_name="name2" #confidential
storage_account_key="password" #confidential 
container_initial_folder="name3" #confidential
container_second_folder="name4" #confidential

def datalake_connector(storage_account_name, storage_account_key):
    global service_client

    datalake_client = DataLakeServiceClient(account_url="{0}://{1}.dfs.core.windows.net".format("https", storage_account_name), credential=storage_account_key)
    print("Client successfuly created!")

    return datalake_client

def create_list_paths(chronological_date, 
                      container_initial_folder="name3", 
                      container_second_folder="name4", 
                      storage_container_name="name1", 
                      storage_account_name="name2"
                      ):
    list_of_paths=list()
    print("1. success")
    paths = file_system_client.get_paths("{0}/{1}/0/{2}/{3}/{4}".format(container_initial_folder, container_second_folder, chronological_date[0], chronological_date[1], chronological_date[2]), recursive=True)
    print("2. success")
    list_of_paths=["abfss://{0}@{1}.dfs.core.windows.net/".format(storage_container_name, storage_account_name)+path.name for path in paths if ".avro" in path.name]
    print("3. success")
    list_of_paths=functools.reduce(operator.iconcat, result, [])

    return list_of_paths

service_client = datalake_connector(storage_account_name, storage_account_key)
file_system_client = service_client.get_file_system_client(file_system=storage_container_name)

try:
    list_of_paths=[]
    executor=ThreadPoolExecutor(max_workers=8)
    print("Start path extraction!")
    list_of_paths=[executor.submit(create_list_paths, i, container_initial_folder, storage_container_name, storage_account_name).result() for i in date_list]

except:
    print("no success")
    print(sys.exc_info())

不幸的是,StorageErrorException 由于某种原因无法处理,我仍然得到以下标准输出:

【问题讨论】:

  • 您可以有多个except-statements 来匹配不同类型的异常。您也可以同时匹配多个 (stackoverflow.com/questions/6470428/…)。只要您可以访问实际的异常类型,就可以了。尝试找出特定异常的定义位置并将其导入。
  • 不,你在更新中做错了。你应该恢复它。
  • 不要定义任何东西。只是try:,...,except:,....
  • 你不可能得到名称错误,因为你删除了所有 StorageErrorException 引用。放置所有代码,而不仅仅是让人们猜测丢失的代码的部分。
  • 我没有说except StorageErrorException:。我说except:

标签: python exception try-except


【解决方案1】:

上市[Python 3.Docs]: Compound statements - The try statement

有几种方法可以实现这一点。这是一个:

try:
    # ...
except StorageErrorException:
    pass
except:
    print(sys.exc_info()[1])

请注意,except: 很棘手,因为您可能会默默地处理不应该处理的异常。另一种方法是捕获代码可能显式引发的任何异常。

try:
    # ...
except StorageErrorException:
    pass
except (SomeException, SomeOtherException, SomeOtherOtherException) as e:
    print(e)

快速浏览[MS.Docs]: filedatalake package 和源代码,发现StorageErrorException(扩展[MS.Docs]: HttpResponseError class)是您需要处理的。


可能要检查[SO]: About catching ANY exception

与捕获异常失败有关,显然有2个同名:

  1. azure.storage.blob._generated.models._models_py3.StorageErrorException(当前已导入)
  2. azure.storage.filedatalake._generated.models._models_py3.StorageErrorException

我不知道原因(我没有使用该包),但考虑到该包引发了另一个包中定义的异常,而它也定义了一个同名包,这似乎很蹩脚。
无论如何,导入正确的异常可以解决问题。

附带说明,在处理这种情况时,不要只导入基本名称,而是使用完全限定名称:

import azure.storage.filedatalake._generated.models.StorageErrorException

【讨论】:

  • 很好,由于某种原因,我记得 python 不允许多个 except 子句,这绝对是最好的方法!
  • 看起来很平衡,我们来试试吧!
  • 我猜这里的AccountIsDisabled就是@Adam.Er8定义的类
  • O,所以第三方包没有定义异常?调查一下。
  • StorageErrorException 不起作用是有原因的。这就是我在更新的答案中试图表达的。 :(
【解决方案2】:

你想比较异常的type,把你的条件改成:

if type(e)==AccountIsDisabled:

示例:

class AccountIsDisabled(Exception):
    pass

print("try #1")
try:
    raise AccountIsDisabled
except Exception as e:
    if type(e)==AccountIsDisabled:
        pass
    else:
        print(e)

print("try #2")
try:
    raise Exception('hi', 'there')
except Exception as e:
    if type(e)==AccountIsDisabled:
        pass
    else:
        print(e)

输出:

try #1
try #2
('hi', 'there')

【讨论】:

  • 感谢您的回答,让我将其附加到我的代码中并让您知道结果!\
  • 不是很地道
  • 好的想法是它有效......所以这是一个解决方案。也许如果我想要更多的例外来超越,我可以采用相同的方法。唯一让我感到困惑的是 Python 如何理解多重异常逻辑中的错误。因此,如果我想超过两个自定义异常,python 如何获得这是一个 AccountIsDisabled 异常而不是 ValueError。我写下我的想法。您的解决方案在任何情况下都有效。
猜你喜欢
  • 2021-10-05
  • 1970-01-01
  • 1970-01-01
  • 2019-03-23
  • 2014-02-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-11-19
相关资源
最近更新 更多