Обработка ошибки 404–Not Found функцией Web.Contents() в Power Query и Power BI

Текст представляет собой адаптированный перевод статьи Chris Webb (Крис Вебб), оригинал – Handling 404–Not Found Errors With Web.Contents() In Power Query And Power BI. Рассматривается англоязычный Power Query.

Об авторе

Крис Вебб (Chris Webb) — независимый эксперт, консультант по технологиям Analysis Services, MDX, Power Pivot, DAX, Power Query и Power BI. Его блог — это кладезь информации на тему перечисленных технологий. Вот уже более 10 лет он пишет про BI-решения от Microsoft. Количество его статей перевалило за 1000! Также Крис выступает на большом количестве различных конференций вроде SQLBits, PASS Summit, PASS BA Conference, SQL Saturdays и участвует в различных сообществах.
Крис любезно разрешил нам переводить его статьи на русский язык. И это одна из них.

Обработка ошибки 404–Not Found функцией Web.Contents() в Power Query и Power BI

Одно из странных свойств функции Web.Contents() в Power Query и Power BI это то, что она не обрабатывает стандартные ошибки привычным в языке М способом. Трудно сказать баг это или фича, но подобная ситуация встречается довольно часто. Поэтому мы решили поделиться описанием проблемы и способом обойти её.

Во-первых, так в чём проблема? Представим, что мы хотим импортировать в Power Query или список курсов UK Microsoft BI and SQL Server компании Technitrain. Для этого можно воспользоваться функцией Web.Contents() и получить данные с RSS feed. Например, так:

let  
   Source = Web.Contents("http://technitrain.com/feed/")  
in  
   Source  

Но что произойдёт, если будет ошибка в адресе URL или другие проблемы на сайте? Следующая ссылка вернёт ошибку 404 – Not Found, т.к. страница не существует:

http://technitrain.com/blahblah

Если мы сделаем такой запрос:

let  
   Source = Web.Contents("http://technitrain.com/blahblah")  
in  
   Source  

Естественно, получим ошибку:

DataSource.Error: Web.Contents failed to get contents from ‘http://technitrain.com/blahblah’ (404): Not Found

(Ошибка источника данных: Web.Contents не удалось получить данные с ‘http://technitrain.com/blahblah’ (404): Не найдено)

p1.png

Хоть это и реальная проблема, попробуем обработать ошибку с помощью оператора try/otherwise:

let  
   Source = try  
               Web.Contents("http://technitrain.com/blahblah")  
            otherwise  
               "Error!"  
in  
   Source  

И это не работает, мы получаем ту же самую ошибку. Что удивительно, в некоторых случаях с более сложным кодом блок try/otherwise срабатывает. Например, здесь:

let  
   Source = try  
               Xml.Tables(  
                Web.Contents("http://technitrain.com/blahblah")  
               )  
            otherwise  
               "Error!"  
in  
   Source  

Ошибка перехватывается:

p2.png

На этом форуме высказывается предположение, что это связано с ленивыми вычислениями. Но мы так и не смогли определить в каких ситуациях это работает, а в каких нет.

Вместо этого, можно обрабатывать конкретные ошибки HTTP, используя опцию ManualStatusHandling функции Web.Contents():

let  
   Source = Web.Contents(  
        "http://technitrain.com/blahblah",  
        [ManualStatusHandling={404}])  
in  
   Source  

Опция ManualStatusHandling принимает список кодов HTTP ошибок. Если запустить пример выше, то мы увидим, что запрос перестал генерировать ошибку.

Следующая проблема – как узнать сработал запрос или нет? Оказывается, определить это можно, просматривая метаданные, связанные с переменной Source. Вот пример как использовать функцию Value.Metadata() применительно к переменной Source:

let  
   Source = Web.Contents(  
       "http://technitrain.com/blahblah",  
       [ManualStatusHandling={404}]),  
   GetMetadata = Value.Metadata(Source)  
in  
   GetMetadata  

Запрос возвращает запись, которая среди прочего содержит HTTP код ответа:

p3.png

Подытожим, для перехвата ошибки 404 можно использовать такой шаблон:

let  
   Source = Web.Contents(  
       "http://technitrain.com/blahblah",  
       [ManualStatusHandling={404}]),  
   GetMetadata = Value.Metadata(Source),  
   GetResponseStatus = GetMetadata[Response.Status],  
   Output = if GetResponseStatus=404 then "Error!" else Source  
in  
   Output
Следующая статья
Предыдущая статья

Комментирование закрыто.

Подпишитесь на нашу рассылку, чтобы не пропустить новые статьи!

Подписка на рассылку NeedForData

Присоединяйтесь к нам на Facebook:
Бесплатная шпаргалка по визуализации
Плакат Как что визуализировать

Плакат Как что визуализировать

© 2017    NeedForData