top of page

Databricks - Casos de suporte - VocĂȘ sabe a diferença entre %run e dbutils.notebook.run()?

Fala dataholics, mais uma dica de milhĂ”es para vocĂȘs, como atuo diretamente na administração e sustentação de Databricks e outras ferramentas, geralmente pegamos casos legais todos os dias, tentarei compartilhar mais casos com vocĂȘs, hoje vou mostrar um tema onde ajudei alguns engenheiros e foi um caso bem interessante.


O que veremos no post de hoje?

  • dbutils.notebook.run() e como funciona

  • %run e como funciona

  • Enviando parĂąmetros para notebooks

  • Usando Widgets

  • LimitaçÔes

  • Spark Context e Spark Session

  • Resumo da utilização de cada um


VocĂȘ jĂĄ precisou realizar a chamada de algum notebook dentro de outro notebook? Se sim, jĂĄ se deparou com esses nomes que citei no tĂ­tulo, caso nĂŁo, temos 2 opçÔes e vou explicar sobre elas.


A primeira opção e mais simples, pois podemos enviar parĂąmetros de forma facilitada Ă© o dbutils.notebook.run(). Com essa função vocĂȘ executa um notebook imediatamente, porĂ©m, o que esta por de trĂĄs dos panos? Vamos ver agora.


Tenho o primeiro notebook chamado notebook1 onde definimos algumas variåveis, agora queremos chamar o notebook2 passando essas variåveis como parùmetros, observe no comando 2, estou passando o caminho do notebook e enviando um valor de 30 que é um timeout, ou seja, ele vai esperar 30 segundos até falhar por timeout e tenho uma lista de parùmetros informando as duas variåveis criadas no comando 1.


E no notebook2 estou apenas pegando os valores dos parĂąmetros recebidos e mostrando na tela.

Esse Ă© um exemplo bem simplista, contudo, em casos mais reais existem vĂĄrios processamentos e lĂłgicas de negĂłcio dentro desse notebook2, vai depender do seu desenvolvimento e necessidade.


Observe que estou usando tanto a função getArgument() quanto a widgets.get(), só para mostrar que é o mesmo efeito, eu falo um pouco disso neste post de parametrização.

Bom vamos à execução desse notebook1:

Primeiro ponto a notar, ele criou um Job Run? Mas o que Ă© isso?

Se vocĂȘ clicar no link vai ver todos os detalhes da execução, tudo como se fosse um Job do Workflows, rodando no cluster All Purpose que vocĂȘ esta conectado, Ă© exatamente um job do Workflows, mas sem estar criado no Workflows, sĂł existe em tempo de execução.

O comando dbutils.notebook.run() chama a API de Job Runs, por isso vocĂȘ consegue enviar parĂąmetros de forma simplificada.


O resultado Ă© o que esperĂĄvamos, ele printou as variĂĄveis enviadas pelo notebook1 e sucesso.


Agora vamos aprofundar o cenårio, para melhor gestão do ambiente realizamos o bloqueio de criação de Jobs nos clusters All Purpose, para ninguém mais criar Jobs sem passar pelo time de administração, o objetivo era somente bloquear a criação e agendamento de novos Jobs, contudo, isso impactou no comando dbutils.notebook.run(), o engenheiro recebia o seguinte erro:

INVALID_PARAMETER_VALUE: The cluster xxxxxxxx does not support jobs workload

Bloquear a criação de Jobs resolveu nosso problema de controle do ambiente, mas gerou esse outro. Foi aí que sugeri o engenheiro ao invés de usar o dbutils.notebook.run e passar a usar o %run.


Contudo, nĂŁo foi tĂŁo simples assim, o %run se comporta diferente do dbutils.notebook.run, ele nĂŁo cria uma Job Run, ele basicamente roda o notebook referenciado como se fosse um comando sĂł, tudo dentro da mesma sessĂŁo e Contexto do Spark, o %run Ă© bem Ăștil no dia a dia, vocĂȘ pode criar notebooks de funçÔes ou parametrizaçÔes default e depois sĂł chamar ele nos demais notebooks, isso facilita na organização de alguns cenĂĄrios.


Porém, o problema aqui era outro, como enviar parùmetros usando o %run?

Simples assim! SQN!

Note que na chamada acima estou passando um valor fixo, infelizmente nĂŁo encontramos uma forma de enviar variĂĄveis, aparentemente nĂŁo tem suporte.

Ele simplesmente envia um valor literal fixo, note que ele nĂŁo envia o valor da variĂĄvel, ele envia os nomes.


Bom, pensei entĂŁo, vamos usar Widgets.

EntĂŁo defini os Widgets no meu notebook1, na chamada do notebook2 nĂŁo envio mais parĂąmetros, pois, ele vai usar os Widgets definidos no notebook1, como ele roda dentro da mesma SessĂŁo do Spark os Widgets ficam visĂ­veis para todos os notebooks chamados via %run, diferente do notebooks.run().

Funcionou top! SQN!


Parece que funcionou, mas temos outro problema, quando trocamos os valores do Widget ele nĂŁo atualiza.

Veja que trocamos as datas, mas o Widget contĂ­nua com valores desatualizados.

Bom tentei mais algumas coisas, inclusive um dbutils.widgets.removeAll() para limpar as referĂȘncias, mas nĂŁo deu bom, de fato temos uma limitação aqui:


Mas somos de TI né, nada pode ficar sem solução, então pensei numa solução relativamente simples, criar uma tabela de controle, onde ela grava os parùmetros e recupera dentro do notebook chamado, assim funcionou sem problemas.


O exemplo Ă© bem simples, cria uma tabela de parĂąmetros, insere os valores que deseja enviar.


drop table if exists tb_parameters;
create table if not exists tb_parameters (dataini date, datafim date);
insert into tb_parameters values('2023-01-01','2023-03-31');

O notebook de referĂȘncia ficou assim:


E a chamada funciona tranquilamente e vocĂȘ pode ajustar os valores a qualquer momento na tabela que eles serĂŁo refletidos.


Ficou curioso sobre as sessÔes do Spark também?


Utilizando dbutils.notebook.run():

Abaixo temos a sessĂŁo e contexto do Spark para o notebook1.

SessĂŁo: 547e3122

Contexto: 75de685d


Quando chamo o notebook 2:

SessĂŁo: 4f272725

Contexto: 75de685d

EntĂŁo ele cria uma nova sessĂŁo do Spark quando roda via Job Run, mas usando o mesmo contexto.


E com o %Run:

SessĂŁo: 547e3122

Contexto: 75de685d

Ou seja, com %Run ele usa a mesma sessĂŁo e contexto do Spark, como se tivesse tudo dentro do mesmo notebook.


Resumindo o que vimos até aqui:


dbutils.notebook.run():

Executa uma chamada na API Job Runs e inicia uma nova sessão Spark para rodar o notebook, aceita parùmetros como se fosse um job normal, não podemos retornar as funçÔes e variåveis para o notebook pai que o executou.


%Run:

Roda dentro da mesma sessĂŁo do Spark, traz todo o conteĂșdo do notebook chamado para dentro do notebook pai, exemplo, funçÔes e variĂĄveis, como se unificasse os notebooks.

NĂŁo consegue enviar parĂąmetros de forma dinĂąmica e tem problemas com uso de Widgets.


É isso, espero que tenha ficado claro, qualquer coisa deixa um comentário ou manda mensagem.


Link do Github:


Fique bem e até a próxima.


Referencias:




Post: Blog2 Post
bottom of page