I have a sample python script that uses the click library:
import click
@click.group()
def cli():
pass
@cli.command()
@click.argument("name", default="User")
def hello(name):
print(f"Hello, {name}!")
if __name__ == "__main__":
cli()
I would like to run the command from a string so it can be called dynamically via code (with a loop over lines in a text file, for example). I have one solution using the CliRunner class, but it comes with the caveat:
This only works in single-threaded systems without any concurrency as it changes the global interpreter state.
This solution looks like:
import shlex
from click.testing import CliRunner
def run_line(line):
runner = CliRunner()
# Split with shlex to allow "quoted values"
# Also use ternary to prevent empty arrays
args = shlex.split(line) if line != "" else [""]
# Get the function from globals, default to no subcommand
command = globals().get(args.pop(0), cli)
result = runner.invoke(command, args)
print(result.output)
run_line("hello World")
The above outputs Hello, World!. I could probably use locks to guard against simultaneous access on files, but that still feels hacky given the note on the CliRunner class. Any ideas?