A practice prompt we wrote. No company or candidate report names it, so it carries no company tag.
How to answer
The parser is five minutes of argparse. The interviewer is checking whether the customer’s operator could run your tool from a script at two in the morning and know what happened.
- Write the command surface before any code. As usage lines:
records import FILE,records validate FILE,records export --format csv|json [--out PATH]. Useadd_subparsers(dest="command", required=True), so a missing command becomes a usage error naming the choices, and bind each subcommand to a function withset_defaults(func=...), so dispatch isreturn args.func(args). - Make
main(argv) -> intthe only place that knows about the terminal. It parses, dispatches and returns an exit code;sys.exit(main())sits under the__main__guard. The work lives in plain functions that return results and never print or exit. - Make import validate first, with the same code. One function returns the problems. Then ask: all or nothing, or load the good rows and write the bad ones to a reject file with their line numbers? Either way, write in one transaction and upsert on the record’s natural key, so a re-run never duplicates rows.
- Say the exit codes aloud. 0 for success, 1 when the data has problems, 2 for bad usage, which
parse_argsraises itself asSystemExit(2). A scheduler reads the code, not the text. - Keep streams separate. Data goes to standard output, so export can be piped; messages go to standard error. Each error names the file, the line and the fix:
orders.csv:14: amount "12,50" is not a number. - Test through
main. Callmain(["validate", str(path)])on a temporary file; assert the return code and captured output. Usage errors raise instead, so usepytest.raises(SystemExit).
The trap is a traceback as the error message. It tells the operator nothing and tells the interviewer you never ran the tool on a bad file.
Follow-ups
What the interviewer may ask next, once your first answer is on the table.
- A file has thousands of good rows and a handful of bad ones. Does import write the good ones, and how does the person running it find the bad ones?
- A nightly job runs validate. How does the scheduler know it failed, without anyone reading the output?
- Export writes to standard output and someone pipes it into head. What happens when head exits early?
Where answers go wrong
- Calling print and sys.exit from deep inside the import logic, so nothing can be tested without a subprocess and nothing can be reused.
- Writing validate and import as separate code paths, so a file that validates clean still fails to import.
Answer this in two minutes
Write the answer you would say out loud. The clock starts with your first word.
Model answer
“Before any code, the command surface, as the operator will type it:” “The records are orders in a CSV file: order_id, customer, amount, keyed on order_id. The exit codes are the contract with whatever runs this: 0 means clean, 1 means the data has problems, 2 means bad usage or a file that isn’t there, and 3 means the environment failed, such as a locked database.