다음을 통해 공유


Notebook을 조율하고 Notebook에서 코드를 모듈화하다.

노트북을 조화롭게 관리하고 노트북에서 코드를 모듈화하는 방법을 알아봅니다. 예제를 참조하고 Notebook 오케스트레이션에 대체 메서드를 사용하는 시기를 이해합니다.

오케스트레이션 및 코드 모듈화 메서드

다음 table은 노트북에서 사용 가능한 오케스트레이션 방법과 코드를 모듈화하는 방법을 비교합니다.

메서드 사용 사례 메모
Databricks 작업 노트북 오케스트레이션(권장) 노트북을 오케스트레이션하는 데 권장되는 방법입니다.

작업 종속성, 일정 및 트리거를 사용하여 복잡한 워크플로를 지원합니다. 프로덕션 워크로드에 대해 강력하고 확장 가능한 접근 방식을 제공하지만 설정 및 구성이 필요합니다.
dbutils.notebook.run() Notebook 오케스트레이션 만약 작업이 parameters동적 set을 통해 Notebook을 반복하는 등의 사용 사례를 지원하지 못할 경우, dbutils.notebook.run()을 사용하십시오.

각 호출에 대해 새 임시 작업을 시작하여 오버헤드를 증가시키고 고급 일정 기능이 부족할 수 있습니다.
작업 영역 파일 코드 모듈화(권장) 코드를 모듈화하는 데 권장되는 방법입니다.

코드를 작업 영역에 저장된 재사용 가능한 코드 파일로 모듈화합니다. 디버깅 및 단위 테스트를 향상하기 위해 리포지토리와 IDE와의 통합을 통해 버전 제어를 지원합니다. 파일 경로 및 종속성을 관리하려면 추가 설정이 필요합니다.
%run 코드 모듈화 작업 영역 파일에 액세스할 수 없는 경우 %run 사용합니다.

인라인으로 실행하여 다른 Notebook에서 함수 또는 변수를 가져오기만 하면 됩니다. 프로토타입 생성에 유용하지만 유지 관리가 더 어려운 긴밀하게 결합된 코드로 이어질 수 있습니다. 매개 변수 전달 또는 버전 제어를 지원하지 않습니다.

%rundbutils.notebook.run()

%run명령을 사용하면 Notebook 내에 다른 Notebook을 포함할 수 있습니다. %run 사용하여 지원 함수를 별도의 Notebook에 배치하여 코드를 모듈화할 수 있습니다. 이를 통해 분석의 단계를 구현하는 Notebook을 연결할 수도 있습니다. %run을 사용하면 호출된 Notebook이 즉시 실행되고 그 안에 정의된 함수와 변수를 호출 Notebook에서 사용할 수 있게 됩니다.

dbutils.notebook API는 Notebook에서 values을 반환하고 parameters을 전달할 수 있게 해주기 때문에 %run을 보완합니다. 이렇게 하면 종속성이 있는 복잡한 워크플로 및 파이프라인을 빌드할 수 있습니다. 예를 들어, 디렉터리에 있는 파일을 getlist하고 이름을 다른 노트북에 전달할 수 있습니다. 이는 %run를 사용해서는 불가능합니다. 반환 values에 따라 if-then-else 워크플로를 만들 수도 있습니다.

%run과 달리 dbutils.notebook.run() 메서드는 Notebook을 실행하는 새 작업을 시작합니다.

모든 dbutils API와 마찬가지로 이러한 메서드는 Python 및 Scala에서만 사용할 수 있습니다. 그러나 dbutils.notebook.run()을 사용하여 R Notebook을 호출할 수 있습니다.

%run을 사용하여 Notebook 가져오기

아래 예제에서 첫 번째 Notebook은 reverse 매직을 사용하여 %run을 실행한 후 두 번째 Notebook에서 사용할 수 있는 함수 shared-code-notebook을 정의합니다.

공유 코드 Notebook

Notebook 가져오기 예제

두 노트북이 작업 영역의 동일한 디렉터리에 있으므로, 현재 실행 중인 노트북을 기준으로 경로를 확인하려면 ./ 접두사를 ./shared-code-notebook에서 사용해야 함을 나타냅니다. Notebook을 디렉터리(예: %run ./dir/notebook)로 구성하거나 절대 경로(예: %run /Users/username@organization.com/directory/notebook)를 사용할 수 있습니다.

참고 항목

  • %run은 Notebook 전체를 인라인으로 실행하기 때문에 셀에 단독으로 있어야 합니다.
  • 을 사용하여 Python 파일을 실행하고 이 파일에 정의된 %run 엔터티를 Notebook으로 가져올 수 import. Python 파일에서 가져오려면 파일을 사용하여 코드 모듈화를 참조하세요. 또는 파일을 Python 라이브러리에 패키지하고, 해당 Python 라이브러리에서 Azure Databricks 라이브러리를 만든 다음, Notebook을 실행하는 데 사용하는 클러스터에 라이브러리를 설치합니다.
  • %run을 사용하여 위젯이 포함된 노트북을 실행하는 경우 기본적으로 지정된 노트북은 위젯의 기본 values설정으로 실행됩니다. 위젯에 values를 전달할 수도 있습니다. Databricks 위젯 사용 방법을 보려면 %run을 참조하세요.

dbutils.notebook.run 사용하여 새 작업 시작

Notebook을 실행하고 해당 종료 값을 반환합니다. 메서드는 즉시 실행되는 임시 작업을 시작합니다.

dbutils.notebook API에서 사용 가능한 메서드는 runexit입니다. parameters 반환 values 모두 문자열이어야 합니다.

run(path: String, timeout_seconds: int, arguments: Map): String

timeout_seconds 매개 변수는 실행의 시간 제한을 제어합니다(0은 시간 제한을 의미하지 않음). run 호출은 지정된 시간 내에 완료되지 않으면 예외를 발생시킵니다. Azure Databricks가 10분을 초과하여 다운된 경우 Notebook 실행은 timeout_seconds에 관계없이 실패합니다.

arguments 매개 변수는 대상 Notebook의 위젯 values 설정합니다. 특히, 실행 중인 Notebook에 A라는 위젯이 있고 ("A": "B") 호출에 대한 인수 매개 변수의 일부로 키-값 쌍 run()를 전달하는 경우 위젯 A의 값을 검색하면 "B"가 반환됩니다. Databricks 위젯 문서에서 위젯을 만들고 작업하기 위한 지침을 찾을 수 있습니다.

참고 항목

  • arguments 매개 변수는 라틴 문자만 허용합니다(ASCII 문자 set). ASCII가 아닌 문자를 사용하면 오류가 반환됩니다.
  • dbutils.notebook API를사용하여 만든 작업은 30일 이내에 완료되어야 합니다.

run 사용 방법

Python

dbutils.notebook.run("notebook-name", 60, {"argument": "data", "argument2": "data2", ...})

Scala

dbutils.notebook.run("notebook-name", 60, Map("argument" -> "data", "argument2" -> "data2", ...))

노트북 간에 구조화된 데이터 전달

이 섹션에서는 Notebook 간에 구조화된 데이터를 전달하는 방법을 보여 줍니다.

Python

# Example 1 - returning data through temporary views.
# You can only return one string using dbutils.notebook.exit(), but since called notebooks reside in the same JVM, you can
# return a name referencing data stored in a temporary view.

## In callee notebook
spark.range(5).toDF("value").createOrReplaceGlobalTempView("my_data")
dbutils.notebook.exit("my_data")

## In caller notebook
returned_table = dbutils.notebook.run("LOCATION_OF_CALLEE_NOTEBOOK", 60)
global_temp_db = spark.conf.get("spark.sql.globalTempDatabase")
display(table(global_temp_db + "." + returned_table))

# Example 2 - returning data through DBFS.
# For larger datasets, you can write the results to DBFS and then return the DBFS path of the stored data.

## In callee notebook
dbutils.fs.rm("/tmp/results/my_data", recurse=True)
spark.range(5).toDF("value").write.format("parquet").save("dbfs:/tmp/results/my_data")
dbutils.notebook.exit("dbfs:/tmp/results/my_data")

## In caller notebook
returned_table = dbutils.notebook.run("LOCATION_OF_CALLEE_NOTEBOOK", 60)
display(spark.read.format("parquet").load(returned_table))

# Example 3 - returning JSON data.
# To return multiple values, you can use standard JSON libraries to serialize and deserialize results.

## In callee notebook
import json
dbutils.notebook.exit(json.dumps({
  "status": "OK",
  "table": "my_data"
}))

## In caller notebook
import json

result = dbutils.notebook.run("LOCATION_OF_CALLEE_NOTEBOOK", 60)
print(json.loads(result))

Scala

// Example 1 - returning data through temporary views.
// You can only return one string using dbutils.notebook.exit(), but since called notebooks reside in the same JVM, you can
// return a name referencing data stored in a temporary view.

/** In callee notebook */
sc.parallelize(1 to 5).toDF().createOrReplaceGlobalTempView("my_data")
dbutils.notebook.exit("my_data")

/** In caller notebook */
val returned_table = dbutils.notebook.run("LOCATION_OF_CALLEE_NOTEBOOK", 60)
val global_temp_db = spark.conf.get("spark.sql.globalTempDatabase")
display(table(global_temp_db + "." + returned_table))

// Example 2 - returning data through DBFS.
// For larger datasets, you can write the results to DBFS and then return the DBFS path of the stored data.

/** In callee notebook */
dbutils.fs.rm("/tmp/results/my_data", recurse=true)
sc.parallelize(1 to 5).toDF().write.format("parquet").save("dbfs:/tmp/results/my_data")
dbutils.notebook.exit("dbfs:/tmp/results/my_data")

/** In caller notebook */
val returned_table = dbutils.notebook.run("LOCATION_OF_CALLEE_NOTEBOOK", 60)
display(sqlContext.read.format("parquet").load(returned_table))

// Example 3 - returning JSON data.
// To return multiple values, use standard JSON libraries to serialize and deserialize results.

/** In callee notebook */

// Import jackson json libraries
import com.fasterxml.jackson.module.scala.DefaultScalaModule
import com.fasterxml.jackson.module.scala.experimental.ScalaObjectMapper
import com.fasterxml.jackson.databind.ObjectMapper

// Create a json serializer
val jsonMapper = new ObjectMapper with ScalaObjectMapper
jsonMapper.registerModule(DefaultScalaModule)

// Exit with json
dbutils.notebook.exit(jsonMapper.writeValueAsString(Map("status" -> "OK", "table" -> "my_data")))

/** In caller notebook */

// Import jackson json libraries
import com.fasterxml.jackson.module.scala.DefaultScalaModule
import com.fasterxml.jackson.module.scala.experimental.ScalaObjectMapper
import com.fasterxml.jackson.databind.ObjectMapper

// Create a json serializer
val jsonMapper = new ObjectMapper with ScalaObjectMapper
jsonMapper.registerModule(DefaultScalaModule)

val result = dbutils.notebook.run("LOCATION_OF_CALLEE_NOTEBOOK", 60)
println(jsonMapper.readValue[Map[String, String]](result))

오류 처리

이 섹션에서는 오류를 처리하는 방법을 보여 줍니다.

Python

# Errors throw a WorkflowException.

def run_with_retry(notebook, timeout, args = {}, max_retries = 3):
  num_retries = 0
  while True:
    try:
      return dbutils.notebook.run(notebook, timeout, args)
    except Exception as e:
      if num_retries > max_retries:
        raise e
      else:
        print("Retrying error", e)
        num_retries += 1

run_with_retry("LOCATION_OF_CALLEE_NOTEBOOK", 60, max_retries = 5)

Scala

// Errors throw a WorkflowException.

import com.databricks.WorkflowException

// Since dbutils.notebook.run() is just a function call, you can retry failures using standard Scala try-catch
// control flow. Here, we show an example of retrying a notebook a number of times.
def runRetry(notebook: String, timeout: Int, args: Map[String, String] = Map.empty, maxTries: Int = 3): String = {
  var numTries = 0
  while (true) {
    try {
      return dbutils.notebook.run(notebook, timeout, args)
    } catch {
      case e: WorkflowException if numTries < maxTries =>
        println("Error, retrying: " + e)
    }
    numTries += 1
  }
  "" // not reached
}

runRetry("LOCATION_OF_CALLEE_NOTEBOOK", timeout = 60, maxTries = 5)

여러 Notebook을 동시에 실행

스레드(Scala, Python) 및 Futures(Scala, Python)와 같은 표준 Scala 및 Python 구문을 사용하여 동시에 여러 Notebook을 실행할 수 있습니다. 예제 Notebook에서는 이러한 구문을 사용하는 방법을 보여 줍니다.

  1. 다음의 네 개 전자 필기장을 다운로드하세요. Notebook은 Scala로 작성됩니다.
  2. Notebook을 작업 영역의 단일 폴더로 가져옵니다.
  3. 동시 실행 Notebook을 실행합니다.

동시에 Notebook 실행

Get 노트북

병렬 Notebook에서 실행

Get 노트북

Notebook 테스트

Get 노트북

2 Notebook 테스트

Get 노트북