Welcome to Software Development on Codidact!
Will you help us build our independent community of developers helping developers? We're small and trying to grow. We welcome questions about all aspects of software development, from design to code to QA and more. Got questions? Got answers? Got code you'd like someone to review? Please join us.
For scripting what are the pros and cons of command line arguments versus capturing input at the start?
Let's say I have a script that needs the user to set X number of variables at the start. One can either
- Pass the arguments in on the command line.
- Start the program and then have the user input the variables with Python's
input()
function or PHP'sfopen("php://stdin", "r")
for example.
What would the pros and cons be and when would I decide to use one method versus the other?
Pros of CLI arguments/flags include: Easier to leverage the tool in another script or via other automation so that …
4y ago
I'd like to move the frame out a little and use that as a discussion for how to make these decisions. Input models …
4y ago
I'm coming down strongly in favor of command-line arguments or options over interactive I/O for a number of reasons: …
1y ago
I would like to add further options to the set of possibilities, namely environment variables and GUI input. Moreover, …
1y ago
@laserkittens and @dmckee has already provided good answers, and I will not copy what's there. Personally, I treat …
4y ago
I largely agree with existing answers, but wanted to add this: In many cases, there is no clear answer one way or the …
1y ago
6 answers
Pros of CLI arguments/flags include:
-
Easier to leverage the tool in another script or via other automation so that user interaction is not required
-
If certain arguments are optional and/or have default values, the user is not burdened with these choices when they are unimportant
-
Once someone has used the tool a few times, it is often faster for them to memorize their preferred parameters or save/alias them than to have to manually input them each time
Cons may include:
-
If the targeted users are not comfortable using a CLI, they may struggle to use the application. Receiving parameters via interactive input may be more user-friendly (especially if interactive error handling/validation is employed to give the user immediate feedback and assistance with invalid options)
-
If the parameters are complex and certain options have conditional relationships upon others, gathering this information at runtime may be more user-friendly
Other considerations:
-
Consider accepting either CLI parameters or gathering parameters at runtime if no arguments are provided
-
Consider a configuration file if options will rarely change or are private, such as passwords/keys
-
If the script operates on a file, also consider receiving input via stdin along with various parameters, which enables data to be piped to the application from multiple sources (i.e., not just from a file, or from a file after being filtered through another tool)
I'd like to move the frame out a little and use that as a discussion for how to make these decisions.
Input models
You've listed two input models, but I think we need to add a third before we begin. I'm going to call them
- Command line arguments
- Interactive read at run-time
- Non-interactive read at run-time (either from standard in or from a file)
The interactive form of reading at run-time involves your program printing prompts and expecting answers that may change what prompts are coming, and seems to be your second. The non-interactive version may involve parsing some input language but does not involving prompting.
Multiple kinds of input
It is common for a program or script to manage two kinds of input:
- Some data that is to be processed
- Instructions about how to process the data or what output to produce
which means that we may want to use more than one class on input in a single tool.
Unix model
I'm going to discuss how to make the decisions under the assumption that we're talking about a Unixish model of how tools (whether built-in, written in some compiled language, or scripted) work together. In other words we're assuming that your input may come from another program and your output may go to a third.
This implies that the data to be processed should be accessible through non-interactive reads because getting two programs to synchronize a ask-answer sequence is a pain.
You may also want to provide a way to specify the data on the command line or even an interactive front-end but those are optional flourishes: non-interactive reading is the core approach for the data you are processing.
Control of how the data should be processed and output produced should be distinct from the main data. This is a prime use-case for command-line arguments. You might also get it from a non-interactive read but if so it comes from different source than the data (perhaps data on standard in and switches in a a config file). Interactive management of the switches is fine, but should be optional because we still want to be able to use the tool in a chain of computations (which means without user intervention).
0 comment threads
I'm coming down strongly in favor of command-line arguments or options over interactive I/O for a number of reasons:
-
Providing arguments on the command line is vastly superior for programmatic invocation (for scripts calling scripts, including but not limited to the tool's own test suite, other scripts calling your script, etc).
-
This makes it easy for the command-line user, too, as they can easily recall and repeat or edit previous invocations using their shell's history mechanism, as well as features like command-line completion to avoid having to type in long and potentially complex file names by hand (or long option names, if you have them; though then your tool probably needs to also supply a small completion configuration for each shell you want to support).
-
This is then also easy to wrap into another API, such as a web front end or a system service.
0 comment threads
I would like to add further options to the set of possibilities, namely environment variables and GUI input. Moreover, I would like to distinguish reading information from stdin
and from other (named) files, as this has some architectural implication.
With the options from the OP and other answers taken into account, this gives the following set of possibilities how configuration input can be provided to an executable:
- Command line arguments
- Environment variables
- Non-interactive input via
stdin
(typed in or via file re-direction) - Input file (opened by name)
- Interactive input via
stdin
- Interactive input via GUI
All of these options have their justifications depending on the circumstances, and it can even make sense to combine some of them - for example providing the name of some configuration file via command line or in an environment variable.
Among the decision criteria - some of them have been mentioned by others - are the following (and for different use cases your answers and the resulting tradeoff will be different):
- What is your user base? Do they need guidance while providing the data? Shall they be able to correct mistakes during entering the data? If this is the case, some interactive form of input is preferable.
- How complex is the data that needs to be provided? Is it simple numbers or nested, possibly even recursive data structures? The more complex, the less suited are command line arguments, environment variables and interactive console input.
- How much data has to be provided? For large data, command line and environment variables can not be used, as there are system limits on their sizes.
- How many individual data items have to be provided? It is not advisable to have lots of environment variables, due to the system limits but also due to the increasing risk of name clashes.
- Is the possibility to automate your program relevant? GUI input is hard to automate, interactive console I/O is easier, but non-interactive forms are easiest.
- Is it desirable to have several levels of configuration, like, system configuration in a file like
/etc/<system-cfg>
, user configuration in~/.<user-cfg>
, shell session configuration in environment variable, process configuration on command line, final changes made interactively? - Is your configuration meant to address your program as a whole, or maybe just some library you use? With environment variables and configuration files you can provide data directly to libraries (bypassing the
main
program), If you provide data via command line or viastdin
, themain
program is always involved and has to forward the data to the library (this is the architectural relevance ofstdin
mentioned above).
0 comment threads
@laserkittens and @dmckee has already provided good answers, and I will not copy what's there.
Personally, I treat cli arguments as the default choice because of the flexibility it gives to scripting. Only choose user input when it's obvious that it's necessary.
A good case where you would like to have a combination is a program where unexpected things may happen during execution that requires user input. Like this:
$ rm file.txt
Are you sure you want to delete file.txt? (y/n)
In this case it's good to have this, but in that case also give the option to pass a parameter that adds a default option. So do it. In other cases this can be quite tricky
$ myprog file.txt
file.txt could not be accessed. Please specify another one:
This would be very tricky to convert to parameters.
0 comment threads
I largely agree with existing answers, but wanted to add this:
In many cases, there is no clear answer one way or the other. Take the program wc
which counts characters and lines. Should the interface be wc file.txt
or cat file.txt | wc
? Compelling arguments can be made for the value of either. Yet we have to pick one.
Actually we don't. wc
supports both. More complex programs support the well known -
parameter, so cat file.txt | some_program --file -
as a way of making it a bit more coherent.
Interactive input falls under this as well. ssh-keygen
will interactively ask for the key type. But with ssh-keygen -t ed25519
it will not ask.
CLI arguments, standard input (from pipe) and interactive input form the three pillars of Unix-style human-computer interaction. All programs should aspire to provide first-class support for all three eventually, even if they won't, just like "all kids" aspire to be astronauts. Imagine a stool with two legs. You can make it work, and it's certainly better than a stool with one leg, and way better than none, but once you get to three legs it gets really good.
Of course you have to start somewhere. For your first leg, just pick one. Whatever you feel is a likely use case for your script, and let users rely on Unix to "improvise" the missing legs:
-
cat
if they want to use args but you support stdin - Shell redirection if they want stdin but you want args
-
expect
if you support interactive but they want scriptable
As your program matures, you can use the experience gained from maintaining it to decide which next method of input you should add support for.
1 comment thread