Data Engineer | 40 questions | 2026
Python Interview Questions and Answers for Data Engineers
Python interview questions for freshers 21
Q1FresherMost askedAnswerHideWhat is the difference between merge, join and concat in pandas?
All three combine DataFrames, but in different ways.
pd.merge(left, right, on=..., how=...): works like a SQL join on column values.howcan beinner,left,rightorouter.df.join(other): a shortcut that joins on the index by default.pd.concat([df1, df2], axis=0|1): stacks frames on top of each other (rows) or side by side (columns). It lines them up by index. It does not match keys.
import pandas as pd
c = pd.DataFrame({"id": [1, 2], "name": ["A", "B"]})
o = pd.DataFrame({"id": [1, 1, 3], "amt": [10, 20, 30]})
print(pd.merge(c, o, on="id", how="left"))
print(pd.concat([c, c], ignore_index=True))
Use validate="one_to_many" in merge to catch duplicate keys by mistake.
What they are checking: Everyday pandas joins
Q2FresherMost askedAnswerHideHow does groupby work in pandas? Give an example with multiple aggregations.
groupby splits the data by one or more keys, runs an aggregation on each group, and joins the results back (split, apply, combine).
import pandas as pd
df = pd.DataFrame({"dept": ["A", "A", "B"], "sal": [10, 20, 30]})
out = df.groupby("dept").agg(total=("sal", "sum"), avg=("sal", "mean"), n=("sal", "size")).reset_index()
print(out)
Named aggregation (above) gives clean column names. size counts all rows, including nulls. count counts only non-null values. Use transform when you want a result with the same shape as the original rows. For example: df["pct"] = df.sal / df.groupby("dept").sal.transform("sum").
What they are checking: Core pandas skills
Q3FresherMost askedAnswerHideHow do you handle missing values in pandas?
First measure the missing values. Then decide for each column whether to drop, fill or flag them.
import pandas as pd, numpy as np
df = pd.DataFrame({"a": [1, np.nan, 3], "b": ["x", None, "z"]})
print(df.isna().sum()) # count nulls per column
df2 = df.dropna(subset=["a"]) # drop rows
df3 = df.fillna({"a": df["a"].median(), "b": "unknown"})
df["a"] = df["a"].ffill() # forward fill for time series
The right choice depends on what the value means. A missing amount might be 0. A missing key should be rejected. Keep an is_missing flag if the gap carries meaning. Never fill values silently in a pipeline. Log how many values you changed.
What they are checking: Data cleaning judgment
Q4FresherMost askedAnswerHideWhat is the difference between a list, tuple, set and dictionary in Python?
They differ in order, whether you can change them, and how fast lookup is.
| Type | Ordered | Mutable | Duplicates | Use |
|---|---|---|---|---|
| list | yes | yes | yes | sequence of records |
| tuple | yes | no | yes | fixed records, dict keys |
| set | no | yes | no | uniqueness, fast membership |
| dict | insertion order | yes | unique keys | key to value lookup |
Membership tests (x in s) are O(1) on average for sets and dicts. They are O(n) for lists. In pipelines, turn a list of ids into a set before you filter large data. |
What they are checking: Python basics
Q5FresherMost askedAnswerHideWhat are generators in Python and why are they useful for data pipelines?
A generator gives values one at a time, only when asked (lazily). It does not build the whole collection in memory.
def read_lines(path):
with open(path) as f:
for line in f:
yield line.rstrip("\n")
def parse(lines):
for ln in lines:
yield ln.split(",")
for row in parse(read_lines("data.csv")):
pass # process one row at a time
Chained generators make a streaming pipeline that uses a constant amount of memory. You can process files bigger than RAM. There are two downsides. A generator can be read only once. You also cannot use an index on it.
What they are checking: Memory-efficient processing
Q6FresherMost askedAnswerHideHow do you read and write Parquet files in Python?
Use pandas with the pyarrow engine (or fastparquet). You can also use PyArrow directly.
import pandas as pd
df = pd.DataFrame({"id": [1, 2], "city": ["KTM", "PKR"]})
df.to_parquet("cities.parquet", engine="pyarrow", compression="snappy")
back = pd.read_parquet("cities.parquet", columns=["id"])
Parquet stores data by column, compresses it, and keeps the types. So reading only some columns is fast. For partitioned datasets use df.to_parquet("out/", partition_cols=["city"]). For files bigger than memory, read one row group at a time with pyarrow.parquet.ParquetFile(...).iter_batches().
What they are checking: Column-based file handling
Q7FresherMost askedAnswerHideHow do you remove duplicates in pandas and keep the latest row per key?
Sort by the timestamp. Then call drop_duplicates on the key and keep the last row.
import pandas as pd
df = pd.DataFrame({"id": [1, 1, 2], "ts": ["2025-01-01", "2025-02-01", "2025-01-05"], "v": ["a", "b", "c"]})
latest = (df.sort_values("ts")
.drop_duplicates(subset="id", keep="last"))
print(latest)
Another way is groupby: df.loc[df.groupby("id")["ts"].idxmax()]. Convert timestamps with pd.to_datetime first. Otherwise, odd formats sort as plain text.
What they are checking: Common coding task
Q8FresherMost askedFree with sign-inAnswerHideHow do you read from and write to S3 using boto3?
Create a client or resource. Then use get_object / put_object, or the helpers upload_file / download_file.
Q9FresherMost askedFree with sign-inAnswerHideHow would you build a simple ETL script in Python (extract, transform, load)?
Split the work into three functions: extract, transform and load. This makes each step easy to test. Log the row counts.
Q10FresherMost askedFree with sign-inAnswerHideWhat is the difference between loc and iloc?
loc selects by label (index values and column names). iloc selects by integer position.
Q11FresherMost askedFree with sign-inAnswerHideExplain the use of pivot, pivot_table and melt in pandas.
pivot changes long data to wide data without aggregating. It needs unique index and column pairs. pivot_table does the same, but it also aggregates duplicates. melt changes wide data to long data.
Q12FresherMost askedFree with sign-inAnswerHideWhat is the GIL?
The Global Interpreter Lock (GIL) is a lock in CPython. It lets only one thread run Python bytecode at a time. It keeps reference counts safe.
Q13FresherMost askedFree with sign-inAnswerHideWrite a function that reads a CSV, filters rows, and writes the result to Parquet.
import pandas as pd
def csv_to_parquet(src, dst, min_amount=100):
df = pd.read_csv(src, usecols=["id", "amount", "date"], parse_dates=["date"])
out = df[df["amount"] >= min_amount]
out.to_parquet(dst, index=False)
return len(df), len(out)
Add checks: the file exists and the expected...
Q14FresherMost askedFree with sign-inAnswerHideWhat is the difference between a shallow copy and a deep copy in Python?
A shallow copy makes a new container, but it points to the same inner objects. A deep copy copies everything, level by level.
Q15FresherMost askedFree with sign-inAnswerHideWhat is the difference between == and is in Python?
== compares values (it calls __eq__). is compares identity: do both names point to the same object?
Q16FresherMost askedFree with sign-inAnswerHideWhat is the difference between a list comprehension and a generator expression?
A list comprehension builds the whole list at once, with square brackets. A generator expression, with parentheses, gives items lazily.
Q17FresherMost askedFree with sign-inAnswerHideHow do you read JSON with nested structures into a flat table in pandas?
Use pd.json_normalize to flatten nested dictionaries. Use record_path for nested lists.
Q18FresherMost askedFree with sign-inAnswerHideWhat is the difference between append in a loop and pd.concat for building a DataFrame?
Adding a row at a time to a DataFrame copies the whole frame each time. This is O(n squared), which is very slow. DataFrame.append was removed in pandas 2.0. Instead, collect the pieces in a list and call pd.concat once. Or build the frame from a list of dicts.
Q19FresherMost askedFree with sign-inAnswerHideHow do you handle secrets and configuration in a Python data pipeline?
Never hard-code or commit credentials. Read settings from the environment or a secrets manager.
Q20FresherFree with sign-inAnswerHideWhat are Python type hints and dataclasses, and why use them in data code?
Type hints document the expected types, and tools such as mypy can check them. Dataclasses write the repeated setup code for classes that mostly hold data.
Q21FresherFree with sign-inAnswerHideWhat is the difference between a Python module, package and script?
A module is a single .py file. A package is a directory of modules. It has an __init__.py file, or it is a namespace package. A script is a file you run directly.
Python interview questions for experienced 10
Q22ExperiencedMost askedAnswerHideHow would you write a pandas DataFrame to a relational database?
Use DataFrame.to_sql with a SQLAlchemy engine. Write in chunks.
import pandas as pd
from sqlalchemy import create_engine
engine = create_engine("sqlite:///demo.db")
df = pd.DataFrame({"id": [1, 2], "amt": [10.5, 20.0]})
df.to_sql("sales", engine, if_exists="append", index=False, chunksize=10_000, method="multi")
Notes: if_exists can be fail, replace or append. to_sql only inserts rows. For upserts (update or insert), load into a staging table. Then run INSERT ... ON CONFLICT or MERGE in SQL. For large PostgreSQL loads, COPY through psycopg is much faster. Keep credentials in environment variables or a secrets manager.
What they are checking: Loading to a database
Q23ExperiencedMost askedFree with sign-inAnswerHideHow can you reduce the memory usage of a pandas DataFrame?
Use smaller dtypes and load less data.
- Make numbers smaller:
pd.to_numeric(s, downcast="integer"). - Turn strings with few distinct values into
category. - Use nullable or
string[pyarrow]dtypes for text. - Read only the columns you need with
usecols. - Delete intermediate DataFrames and read in chunks.
Q24ExperiencedMost askedFree with sign-inAnswerHideWhat is the difference between apply, map and vectorized operations in pandas?
Vectorized operations run in compiled code on whole columns. They are the fastest. map and apply call a Python function for each element or row, so they are much slower.
Q25ExperiencedMost askedFree with sign-inAnswerHideHow do you use multiprocessing in Python for data processing, and how is it different from threading?
Because of the GIL, threads do not run Python code in parallel. So use threads for I/O-bound work and processes for CPU-bound work.
Q26ExperiencedMost askedFree with sign-inAnswerHideHow do you list all objects under an S3 prefix in boto3 when there are more than 1000?
Use a paginator. It follows the continuation tokens for you.
Q27ExperiencedMost askedFree with sign-inAnswerHideHow do you work with dates and time zones in pandas?
Parse to datetime. Make the time zone explicit. Convert only at the edges.
Q28ExperiencedMost askedFree with sign-inAnswerHideExplain how you would log and handle errors in a Python ETL job.
Use the logging module with levels. Catch specific exceptions. For each error, decide whether to retry, skip or fail.
Q29ExperiencedMost askedFree with sign-inAnswerHideWhat are decorators and context managers, and where do you use them in pipelines?
A decorator wraps a function to add behavior. A context manager handles setup and cleanup around a with block.
Q30ExperiencedMost askedFree with sign-inAnswerHideHow do you unit test a data transformation function?
Write transformations as pure functions. They take a DataFrame and return a DataFrame. Then test them with small hand-made inputs using pytest.
Q31ExperiencedMost askedFree with sign-inAnswerHideHow do you process files concurrently when downloading many objects from S3?
Downloads wait on the network (I/O-bound), so use a thread pool.
Scenario based Python interview questions 9
Q32ExperiencedMost askedScenarioAnswerHideHow do you process a CSV file too large to fit in memory with pandas?
Read it in chunks. Aggregate or write out each chunk. Never hold all the data at once.
import pandas as pd
totals = {}
for chunk in pd.read_csv("big.csv", chunksize=500_000, usecols=["region", "amount"],
dtype={"region": "category"}):
part = chunk.groupby("region")["amount"].sum()
for k, v in part.items():
totals[k] = totals.get(k, 0) + v
print(totals)
Also do these things. Load only the columns you need (usecols). Choose smaller dtypes. Parse dates explicitly. Convert the file to Parquet once. If the data keeps growing, move to DuckDB, Polars (lazy mode), Dask or Spark.
What they are checking: Practical large-file handling
Q33ExperiencedMost askedScenarioAnswerHideHow do you validate data quality in a Python pipeline?
Validate at the edges: right after reading and right before writing. Check the schema, nulls, uniqueness, ranges and links between tables (referential integrity). Fail the job, or set bad rows aside.
import pandas as pd
df = pd.DataFrame({"id": [1, 2, 2], "age": [25, -3, 40]})
errors = []
if df["id"].duplicated().any():
errors.append("duplicate ids")
bad = df[~df["age"].between(0, 120)]
if not bad.empty:
errors.append(f"{len(bad)} rows with invalid age")
print(errors)
Useful libraries: Pandera, Great Expectations, Pydantic (row by row) and dbt tests. Good practice: write rejected rows to a quarantine table with a reason. Track row counts in and out. Alert when the failure rate crosses a limit. Do not drop data silently.
What they are checking: Reliability mindset
Q34ExperiencedMost askedScenarioFree with sign-inAnswerHideHow do you make a Python data pipeline idempotent?
Idempotent means that running a job twice leaves the same final state as running it once.
Q35ExperiencedMost askedScenarioFree with sign-inAnswerHideHow would you speed up a slow pandas script?
Profile first (%timeit, cProfile). Then fix the biggest cost.
Q36ExperiencedMost askedScenarioFree with sign-inAnswerHideA nightly Python script that loads data into the database ran twice and created duplicates. How do you fix it and prevent it?
Fix the data first. Then change the design so a rerun does no harm.
Q37ExperiencedMost askedScenarioFree with sign-inAnswerHideHow do you do an upsert into a database from Python?
Load the batch into a staging table. Then merge it into the target table with one SQL statement, inside a transaction.
Q38ExperiencedMost askedScenarioFree with sign-inAnswerHideHow do you handle API pagination and rate limits when extracting data with Python requests?
Loop until there is no next page. Reuse one session. Respect rate limits. Retry temporary errors with backoff (wait longer after each failure).
Q39ExperiencedMost askedScenarioFree with sign-inAnswerHideHow do you merge two large DataFrames efficiently and avoid a memory explosion?
Make both sides smaller first. Then merge. Watch out for duplicate keys.
Q40ExperiencedMost askedScenarioFree with sign-inAnswerHideHow do you implement an incremental extract in Python using a watermark?
Save the highest value of a column that only grows (such as updated_at or an id) from the last successful run. Then query only the rows beyond it. This saved value is called a watermark.