Bird
Raised Fist0
Apache Airflowdevops~20 mins

Creating custom operators in Apache Airflow - Practice Exercises

Choose your learning style10 modes available
Challenge - 5 Problems
🎖️
Custom Operator Mastery
Get all challenges correct to earn this badge!
Test your skills under time pressure!
🧠 Conceptual
intermediate
1:30remaining
Purpose of Custom Operators in Airflow

Why would you create a custom operator in Apache Airflow instead of using built-in operators?

ATo encapsulate reusable logic specific to your workflows that built-in operators do not provide.
BBecause built-in operators cannot be used in DAGs.
CTo avoid writing any Python code in your DAG files.
DTo automatically speed up task execution without any configuration.
Attempts:
2 left
💡 Hint

Think about when you need to do something unique or repetitive in your workflows.

💻 Command Output
intermediate
2:00remaining
Output of Custom Operator Execution

Given this custom operator code snippet, what will be printed when the task runs?

Apache Airflow
from airflow.models import BaseOperator
from airflow.utils.decorators import apply_defaults

class HelloOperator(BaseOperator):
    @apply_defaults
    def __init__(self, name: str, **kwargs):
        super().__init__(**kwargs)
        self.name = name

    def execute(self, context):
        print(f"Hello, {self.name}!")

# Assume this operator is used in a DAG with name='Airflow'
ANo output printed
BHello, Airflow!
CError: __init__ missing required positional argument
DHello, name!
Attempts:
2 left
💡 Hint

Look at how the name parameter is used in execute.

❓ Configuration
advanced
2:30remaining
Correct Custom Operator Initialization

Which option correctly defines a custom operator that accepts a file_path parameter and passes other arguments properly to the base class?

A
class FileOperator(BaseOperator):
    def __init__(self, file_path, **kwargs):
        super().__init__(**kwargs)
        self.file_path = file_path
B
class FileOperator(BaseOperator):
    def __init__(self, **kwargs):
        self.file_path = kwargs.pop('file_path')
        super().__init__(**kwargs)
C
class FileOperator(BaseOperator):
    def __init__(self, file_path, **kwargs):
        self.file_path = file_path
        super().__init__(**kwargs)
D
class FileOperator(BaseOperator):
    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        self.file_path = kwargs['file_path']
Attempts:
2 left
💡 Hint

Remember to call super().__init__ before using self attributes.

❓ Troubleshoot
advanced
2:00remaining
Error Raised by Incorrect Custom Operator Code

What error will this custom operator code raise when instantiated?

Apache Airflow
class BadOperator(BaseOperator):
    def __init__(self, param, **kwargs):
        self.param = param
        super().__init__(**kwargs)
ARuntimeError: Task instance failed
BAttributeError: 'BadOperator' object has no attribute 'param'
CTypeError: __init__() missing 1 required positional argument: 'task_id'
DNo error, runs fine
Attempts:
2 left
💡 Hint

Check the order of super().__init__ call and attribute assignment.

🔀 Workflow
expert
3:00remaining
Order of Steps to Create and Use a Custom Operator

What is the correct order of steps to create and use a custom operator in Airflow?

A3,1,2,4
B2,1,3,4
C1,3,2,4
D1,2,3,4
Attempts:
2 left
💡 Hint

Think about writing code, importing it, then using it in the DAG.

Practice

(1/5)
1. What is the main purpose of creating a custom operator in Airflow?
easy
A. To install new Airflow plugins automatically
B. To change the Airflow webserver UI appearance
C. To configure the Airflow scheduler settings
D. To define reusable tasks with custom logic inside the execute method

Solution

  1. Step 1: Understand what custom operators do

    Custom operators let you create tasks that run your own code inside Airflow workflows.
  2. Step 2: Identify where custom logic is placed

    This logic is placed inside the execute method of the operator class.
  3. Final Answer:

    To define reusable tasks with custom logic inside the execute method -> Option D
  4. Quick Check:

    Custom operator = reusable task logic [OK]
Hint: Custom operators run your code in the execute() method [OK]
Common Mistakes:
  • Confusing UI or scheduler settings with operators
  • Thinking operators install plugins
  • Believing custom operators change Airflow core behavior
2. Which of the following is the correct way to start defining a custom operator class in Airflow?
easy
A. operator MyOperator extends BaseOperator:
B. class MyOperator(BaseOperator):
C. class MyOperator():
D. def MyOperator():

Solution

  1. Step 1: Recall Python class syntax for inheritance

    In Python, to inherit from a class, use class ClassName(BaseClass):.
  2. Step 2: Match Airflow custom operator syntax

    Airflow custom operators inherit from BaseOperator, so the correct syntax is class MyOperator(BaseOperator):.
  3. Final Answer:

    class MyOperator(BaseOperator): -> Option B
  4. Quick Check:

    Python class inheritance = class MyOperator(BaseOperator): [OK]
Hint: Custom operators inherit BaseOperator with class syntax [OK]
Common Mistakes:
  • Using function definition instead of class
  • Omitting BaseOperator inheritance
  • Using incorrect syntax like 'operator' keyword
3. Given this custom operator code snippet, what will be printed when the task runs?
from airflow.models import BaseOperator
from airflow.utils.decorators import apply_defaults

class PrintOperator(BaseOperator):
    @apply_defaults
    def __init__(self, message: str, **kwargs):
        super().__init__(**kwargs)
        self.message = message

    def execute(self, context):
        print(f"Message: {self.message}")

# Task instance runs with message='Hello Airflow'
medium
A. Message: Hello Airflow
B. Hello Airflow
C. Message: message
D. Error: missing execute method

Solution

  1. Step 1: Understand the execute method output

    The execute method prints the string with prefix "Message:" followed by the message attribute.
  2. Step 2: Substitute the message value

    The task runs with message='Hello Airflow', so the print outputs "Message: Hello Airflow".
  3. Final Answer:

    Message: Hello Airflow -> Option A
  4. Quick Check:

    execute prints 'Message: ' + message [OK]
Hint: execute() prints 'Message: ' plus the message string [OK]
Common Mistakes:
  • Forgetting the 'Message:' prefix in print
  • Confusing attribute name with string literal
  • Assuming execute method is missing
4. What is wrong with this custom operator code?
from airflow.models import BaseOperator

class BadOperator(BaseOperator):
    def __init__(self, param):
        self.param = param

    def execute(self, context):
        print(self.param)
medium
A. param should be a class variable, not instance variable
B. execute method should not have context parameter
C. Missing call to super().__init__() in __init__ method
D. BaseOperator cannot be inherited

Solution

  1. Step 1: Check __init__ method for BaseOperator inheritance

    When inheriting BaseOperator, you must call super().__init__(**kwargs) to initialize the base class properly.
  2. Step 2: Identify missing super() call

    The code does not call super().__init__()</>, so Airflow internal setup will fail.
  3. Final Answer:

    Missing call to super().__init__() in __init__ method -> Option C
  4. Quick Check:

    Always call super().__init__() in custom operator init [OK]
Hint: Always call super().__init__() in __init__ [OK]
Common Mistakes:
  • Omitting super().__init__() call
  • Removing context parameter from execute
  • Misunderstanding inheritance rules
5. You want to create a custom operator that accepts a list of filenames and prints each filename during execution. Which code snippet correctly implements this behavior?
hard
A. class FilePrinterOperator(BaseOperator): @apply_defaults def __init__(self, files: list, **kwargs): super().__init__(**kwargs) self.files = files def execute(self, context): for f in self.files: print(f)
B. class FilePrinterOperator(BaseOperator): def __init__(self, files): self.files = files def execute(self): for f in files: print(f)
C. class FilePrinterOperator(BaseOperator): @apply_defaults def __init__(self, files: str, **kwargs): super().__init__(**kwargs) self.files = files def execute(self, context): print(self.files)
D. class FilePrinterOperator(BaseOperator): @apply_defaults def __init__(self, files: list, **kwargs): super().__init__(**kwargs) self.files = files def execute(self, context): print(files)

Solution

  1. Step 1: Check constructor and inheritance

    class FilePrinterOperator(BaseOperator): @apply_defaults def __init__(self, files: list, **kwargs): super().__init__(**kwargs) self.files = files def execute(self, context): for f in self.files: print(f) correctly uses @apply_defaults, calls super().__init__(**kwargs), and stores the list in self.files.
  2. Step 2: Verify execute method logic

    class FilePrinterOperator(BaseOperator): @apply_defaults def __init__(self, files: list, **kwargs): super().__init__(**kwargs) self.files = files def execute(self, context): for f in self.files: print(f) loops over self.files and prints each filename, matching the requirement.
  3. Final Answer:

    Option A correctly implements the custom operator to print each filename -> Option A
  4. Quick Check:

    Use self.files list and loop in execute() [OK]
Hint: Use self.files list and loop inside execute() [OK]
Common Mistakes:
  • Not calling super().__init__()
  • Using wrong parameter types
  • Referencing variables without self.
  • Missing context parameter in execute
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard