However, when I start development of new code I always use a script that starts off with traceback and pdb, something like this:
# some WIP code that maybe raises an exception
raise BaseException("oh no, exception!")
if __name__ == "__main__":
ret = main()
python -i script.py
I've programmed Python for years and never knew this. I'm not sure how well this handles errors. Tab complete works, only thing that is missing is needing to wrap help(<func>) to see signatures. I'm enjoying the standard lib interpreter.
If you're on linux it's not _that_ bad without it since the shell sort of acts like the notebook (with an equally horrible markup language). The help() and tab-complete and _ __ ___ for last 3 values works, time python <file>.py can benchmark, -i or pdb.set_trace does the debugging. It doesn't keep a persistent history though so the workflow is sort of different.
So I use both, particularly for plots and images knowing IPython is very helpful for working with the notebooks.