How do you manage Python memory effectively, and what do you consider when initializing a Spark session?
Implement a planner that converts workload and executor inputs into a safe Spark configuration. It must reserve Python memory overhead, avoid oversized batches, choose a practical partition count, and represent dynamic allocation settings.
Implement create_spark_plan(data_size_mb, executor_memory_mb, executor_cores, python_memory_mb, dynamic_allocation). Return a dictionary containing the calculated memory, partition, batch, and Spark configuration values.
def create_spark_plan(data_size_mb, executor_memory_mb, executor_cores, python_memory_mb, dynamic_allocation):