Sometimes I fire up a python
interpreter in my terminal for quick
prototyping, but often forget what the standard library method signatures are.
For example, how should I invoke subprocess.call
?
The most straightforward action at this point is to simply google it, no shame. The first result helpfully redirects me to the official python documentation, as one would expect.
From the documentation, I’d run something like this:
subprocess.call(["ls", "-al"], cwd='/tmp')
What if I wanted to figure out the correct way to do so from the command line though?
bpython
Enter bpython
:
bpython
is a fancy interface to the Python interpreter for Linux, BSD, OS X and Windows (with some work). bpython is released under the MIT License. It has the following (special) features:
It should be available in your favorite linux distribution. Once it’s installed, a typical session would look like this:
% bpython
bpython version 0.22.1 on top of Python 3.10.2 /usr/bin/python
>>> import subprocess
>>> subprocess.call(["ls", "-la"], cwd='/tmp')
┌──────────────────────────────────────────────────────────────────────────────────────┐
│ subprocess.call: (*popenargs, timeout=None, **kwargs) │
│ call │
│ Run command with arguments. Wait for command to complete or │
│ timeout, then return the returncode attribute. │
│ │
│ The arguments are the same as for the Popen constructor. Example: │
│ │
│ retcode = call(["ls", "-l"]) │
└──────────────────────────────────────────────────────────────────────────────────────┘
To see all Popen
arguments:
>>> subprocess.Popen(
┌──────────────────────────────────────────────────────────────────────────────────────┐
│ subprocess.Popen: (args, bufsize=-1, executable=None, stdin=None, stdout=None, │
│ stderr=None, preexec_fn=None, close_fds=True, shell=False, cwd=None, env=None, │
│ universal_newlines=None, startupinfo=None, creationflags=0, restore_signals=True, │
│ start_new_session=False, pass_fds=(), *, user=None, group=None, extra_groups=None, │
│ encoding=None, errors=None, text=None, umask=-1, pipesize=-1) │
│ Popen │
│ Execute a child program in a new process. │
│ │
│ For a complete description of the arguments see the Python documentation. │
│ │
│ Arguments: │
│ args: A string, or a sequence of program arguments. │
# output truncated for brevity; bpython displays it all
As you can see, it wouldn’t be difficult to have a rough idea of which arguments are available and what they do.
I could keep going:
>>> p = subprocess.run(["ls", "-la"], cwd='/tmp')
>>> p.
┌──────────────────────────────────────────────────────────────────────────────────────┐
│ args check_returncode returncode stderr │
│ stdout │
└──────────────────────────────────────────────────────────────────────────────────────┘
>>> p.args.
┌──────────────────────────────────────────────────────────────────────────────────────┐
│ append clear copy count extend │
│ index insert pop remove reverse │
│ sort │
└──────────────────────────────────────────────────────────────────────────────────────┘
Out-of-the-box it also displays autosuggestions based on the history of my previous commands1. It also supports python 3. For the full list of features, refer to https://bpython-interpreter.org/.
ipython
Alternatively ipython
2 is comparable to bpython
, however I find it a bit less user-friendly out-of-the-box:
% ipython
iPython 3.10.2 (main, Jan 15 2022, 19:56:27) [GCC 11.1.0]
Type 'copyright', 'credits' or 'license' for more information
IPython 8.0.1 -- An enhanced Interactive Python. Type '?' for help.
In [1]: import subprocess
In [2]: subprocess.
builtins contextlib io select threading
call() DEVNULL list2cmdline() selectors time
CalledProcessError errno os signal TimeoutExpired
check_call() fcntl PIPE STDOUT types
check_output() getoutput() Popen SubprocessError warnings
In [2]: subprocess.call(
abs() False ModuleNotFoundError SystemError
all() FileExistsError NameError SystemExit
any() FileNotFoundError next() TabError
ArithmeticError filter() None timeout=
ascii() float NotADirectoryError TimeoutError
The tab completion after call(
doesn’t display the documentation for it. However, appending a ?
works:
% ipython
Python 3.10.2 (main, Jan 15 2022, 19:56:27) [GCC 11.1.0]
Type 'copyright', 'credits' or 'license' for more information
IPython 8.0.1 -- An enhanced Interactive Python. Type '?' for help.
In [1]: import subprocess
In [2]: subprocess.call?
Signature: subprocess.call(*popenargs, timeout=None, **kwargs)
Docstring:
Run command with arguments. Wait for command to complete or
timeout, then return the returncode attribute.
The arguments are the same as for the Popen constructor. Example:
retcode = call(["ls", "-l"])
File: /usr/lib/python3.10/subprocess.py
Type: function
Furthermore, subprocess.Popen?
opens a pager with the documentation for the method.
Conclusion
Both bpython
and ipython
are excellent tools to enhance the user experience
within the python interpreter, being great for quick prototyping,
experimentation or exploration. bpython
seems a bit more user-friendly and
intuitive upon first usage, ipython
takes a bit getting used to.
fish
shell andzsh-autosuggestions
users should know what I’m talking about. ↩︎ipython
has been around for longer and these days there’s the whole Jupyter Notebook ecosystem around it. ↩︎