Ausführen eines Databricks-Notebooks über ein anderes Notebook

Wichtig

Verwenden Sie für die Orchestrierung von Notebooks Databricks-Aufträge. Verwenden Sie in Szenarien zur Codemodularisierung Arbeitsbereichsdateien. Sie sollten die in diesem Artikel beschriebenen Techniken nur verwenden, wenn Ihr Anwendungsfall nicht mithilfe eines Databricks-Auftrags implementiert werden kann, z. B. beim Durchlaufen von Notebooks über einen dynamischen Parametersatz oder wenn Sie keinen Zugriff auf Arbeitsbereichsdateien haben. Weitere Informationen finden Sie unter Databricks-Aufträge und Freigeben von Code.

Gegenüberstellung von %run und dbutils.notebook.run()

Mit dem Befehl %run können Sie ein anderes Notebook in ein Notebook einbeziehen. Sie können %run verwenden, um Ihren Code zu modularisieren, indem Sie z. B. unterstützende Funktionen in einem separaten Notebook platzieren. Sie können damit auch Notebooks verketten, die die Schritte in einer Analyse implementieren. Wenn Sie %run verwenden, wird das aufgerufene Notebook sofort ausgeführt, und die darin definierten Funktionen und Variablen werden im aufrufenden Notebook verfügbar.

Die dbutils.notebook-API ergänzt %run, da Sie Parameter an ein Notebook übergeben und Werte aus einem Notebook erhalten können. Dadurch können Sie komplexe Workflows und Pipelines mit Abhängigkeiten erstellen. So können Sie beispielsweise eine Liste von Dateien in einem Verzeichnis abrufen und die Namen an ein anderes Notebook weitergeben, was mit %run nicht möglich ist. Sie können auch IF-THEN-ELSE-Workflows auf Grundlage von Rückgabewerten erstellen oder andere Notebooks über relative Pfade aufrufen.

Im Gegensatz zu %run startet die dbutils.notebook.run()-Methode einen neuen Auftrag zum Ausführen des Notebooks.

Diese Methoden sind wie alle dbutils-APIs nur in Python und Scala verfügbar. Sie können jedoch mithilfe von dbutils.notebook.run() ein R-Notebook aufrufen.

Verwenden von %run zum Importieren eines Notebooks

In diesem Beispiel wird im ersten Notebook die Funktion reverse definiert, die im zweiten Notebook verfügbar ist, nachdem Sie den Magic-Befehl %run zum Ausführen von shared-code-notebook verwendet haben.

shared-code-notebook

Beispiel für den Import eines Notebooks

Da sich beide Notebooks im gleichen Verzeichnis im Arbeitsbereich befinden, verwenden Sie das Präfix ./ in ./shared-code-notebook, um anzugeben, dass der Pfad relativ zum aktuell ausgeführten Notebook aufgelöst werden soll. Sie können Notebooks in Verzeichnissen organisieren (z. B. %run ./dir/notebook) oder einen absoluten Pfad wie %run /Users/username@organization.com/directory/notebook angeben.

Hinweis

  • %run muss sich in einer eigenen Zelle befinden, da hiermit das gesamte Notebook inline ausgeführt wird.
  • Sie können %runnicht verwenden, um eine Python-Datei auszuführen und einen import-Vorgang vorzunehmen, um die in dieser Datei definierten Entitäten in ein Notebook zu importieren. Informationen zum Importieren aus einer Python-Datei finden Sie unter Modularisieren Ihres Codes mithilfe von Dateien. Sie können die Datei auch in einer Python-Bibliothek packen, eine Azure Databricks-Bibliothek aus dieser Python-Bibliothek erstellen und die Bibliothek in dem Cluster installieren, den Sie zum Ausführen Ihres Notebooks verwenden.
  • Wenn Sie ein %run verwenden, um ein Notebook auszuführen, das Widgets enthält, wird das angegebene Notebook standardmäßig mit den Standardwerten des Widgets ausgeführt. Sie können auch Werte an Widgets übergeben. Weitere Informationen finden Sie unter Verwenden von Databricks-Widgets mit %run.

dbutils.notebook API

In der dbutils.notebook-API stehen die Methoden run und exit zur Verfügung. Sowohl Parameter als auch Rückgabewerte müssen Zeichenfolgen sein.

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

Führt ein Notebook aus und gibt dessen EXIT-Wert zurück. Die Methode startet einen kurzlebigen Auftrag, der sofort ausgeführt wird.

Der Parameter timeout_seconds steuert das Zeitlimit der Ausführung (0 bedeutet ohne Zeitlimit). Der Aufruf von run löst eine Ausnahme aus, wenn er nicht innerhalb der angegebenen Zeit beendet wird. Wenn Azure Databricks länger als 10 Minuten ausfällt, schlägt die Ausführung des Notebooks unabhängig von timeout_seconds fehl.

Der Parameter arguments legt die Widgetwerte des Zielnotebooks fest. Wenn das von Ihnen ausgeführte Notebook über ein Widget mit dem Namen A verfügt und Sie das Schlüssel-Wert-Paar ("A": "B") als Teil der Argumente an den Aufruf von run() übergeben, wird "B" beim Abrufen des Werts des Widgets A zurückgegeben. Eine Anleitung zum Erstellen und Verwenden von Widgets finden Sie im Artikel zu Databricks-Widgets.

Hinweis

  • Der Parameter arguments akzeptiert nur lateinische Zeichen (ASCII-Zeichensatz). Die Verwendung von Nicht-ASCII-Zeichen führt zu einem Fehler.
  • Aufträge, die unter Verwendung der dbutils.notebook-API erstellt werden, müssen innerhalb von maximal 30 Tagen abgeschlossen werden.

run Verwendung

Python

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

Scala

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

run Beispiel

Angenommen, Sie haben ein Notebook namens workflows mit einem Widget namens foo, das den Wert des Widgets ausgibt:

dbutils.widgets.text("foo", "fooDefault", "fooEmptyLabel")
print(dbutils.widgets.get("foo"))

Die Ausführung von dbutils.notebook.run("workflows", 60, {"foo": "bar"}) liefert folgendes Ergebnis:

Notebook mit Widget

Das Widget hatte den Wert "bar", den Sie über dbutils.notebook.run() übergeben haben (anstelle des Standardwerts).

exit(value: String): void Beendet ein Notebook mit einem Wert. Wenn Sie ein Notebook mit der run-Methode aufrufen, wird dieser Wert zurückgegeben.

dbutils.notebook.exit("returnValue")

Der Aufruf von dbutils.notebook.exit in einem Auftrag führt zum erfolgreichen Abschluss des Notebooks. Wenn Sie einen Auftragsfehler verursachen möchten, lösen Sie eine Ausnahme aus.

Beispiel

Im folgenden Beispiel übergeben Sie Argumente an DataImportNotebook und führen verschiedene Notebooks (DataCleaningNotebook oder ErrorHandlingNotebook) basierend auf dem Ergebnis von DataImportNotebook aus.

Beispiel mit „if-else“

Wenn der Code ausgeführt wird, wird ein Link zum ausgeführten Notebook angezeigt:

Link zum ausgeführten Notebook

Klicken Sie auf den Notebooklink Notebookauftrag #xxxx, um die Details der Ausführung anzuzeigen.

Ergebnis einer kurzlebigen Notebookausführung

Übergeben strukturierter Daten

In diesem Abschnitt wird veranschaulicht, wie strukturierte Daten zwischen Notebooks übergeben werden.

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, you can 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))

Fehlerbehandlung

In diesem Abschnitt wird die Behandlung von Fehlern veranschaulicht.

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)

Gleichzeitiges Ausführen mehrerer Notebooks

Sie können mehrere Notebooks gleichzeitig ausführen, indem Sie Standardkonstrukte von Scala und Python wie Threads (Scala, Python) und Futures (Scala, Python) verwenden. Die Beispielnotebooks veranschaulichen die Nutzung dieser Konstrukte.

  1. Laden Sie die folgenden 4 Notebooks herunter. Die Notebooks wurden in Scala geschrieben.
  2. Importieren Sie die Notebooks in einen einzelnen Ordner im Arbeitsbereich.
  3. Führen Sie das Notebook gleichzeitig aus.

Gleichzeitiges Ausführen des Notebooks

Notebook abrufen

Ausführen in parallelem Notebook

Notebook abrufen

Test des Notebooks

Notebook abrufen

Test-2 des Notebooks

Notebook abrufen