Pythonic way to wrap a subprocess call that takes a lot of parameters?
<p>I am writing a python script that provides a more user friendly API to a command line tool. Some of the necessary command calls take a lot of parameters (up to around 10 sometimes), but that is not good practice in Python. They can't just be defaults; it has to be possible to set all the parameters for a given call.</p>

<p>My current structure is an API class that has functions such as expose_image(), and then an interface class to handle the construction of the subprocess command and the call. I don't see that adding more classes will help, as the API class still has to generate and pass the parameters in some way.</p>

<p>One solution I have come up with is to fill a dictionary or namedtuple with the parameters and pass it as **kwargs, which makes things look a little nicer, but less explicit.</p>

<p>Is there a better way of handling this?</p>

<p>Thanks!</p>

<p>It is commendable that you want to build a Pythonic API rather than just an API for this command.</p>

<p>I'm not sure why you disregard default parameters though? If the default is <code>None</code>, you could treat that as a guide to not add things to the command line.</p>

<p>For example, suppose you want to call the tree command. You could have something like:</p>

<pre><code>def my_tree(dirs_only=False, full_prefix=False, max_level=None, pattern=None):
   cmd_line = ['tree']
   if dirs_only:
       cmd_line.append('-d')
   if full_prefix:
       cmd_line.append('-f')
   if max_level is not None:
       cmd_line.append('-L')
       cmd_line.append(str(max_level))
   if pattern is not None:
       cmd_line.append('-P')
       cmd_line.append(pattern)
   subprocess.do_something_with(cmd_line)
</code></pre>

<p>Callers of <code>my_tree</code> could then interact with it like in the shell:</p>

<pre><code>my_tree()
my_tree(dirs_only=True)
my_tree(pattern='Foo*')
my_tree(pattern='Foo*', max_level=2, full_prefix=True)
</code></pre>

<p>In languages such as Java, C# or Dart, you often see "fluent" APIs, and perhaps those might help. It would result in code such as:</p>

<pre><code>my_tree().call()
my_tree().dirs_only().call()
my_tree().with_pattern('Foo*').call()
my_tree() \
    .with_pattern('Foo*') \
    .with_max_level(2) \
    .full_prefix() \
    .call()
</code></pre>

<p>Though the invocation looks nicer, there is a lot of boilerplate you need to write in order to obtain said niceity, which definitely feels a little bit un-Pythonic.</p>

python subprocess parameter-passing args kwargs