I have functions that return some results. I would like to access those functions as libraries: they will be imported and used in some larger scripts. That is straightforward. However, I would like to use those functions as separate scripts which will output the results to stdout
for piping purposes. Does it make sense to write my function this way?
def myfunction(params=(), to_stdout=False):
result = whatever_i_want_to_process(params)
if to_stdout is True:
sys.stdout.writelines(result)
return result
Or are there better, more efficient, and more intuitive ways of doing what I want?
EDIT 1
To be more specific, each function takes a raw input (either from stdin
or a raw string), and adds something to it:
def add_name(content, to_stdout=False):
result = content + "\nadded name"
if to_stdout is True:
sys.stdout.writelines(result)
return result
def add_surname(content, to_stdout=False):
result = content + "\nadded surname"
if to_stdout is True:
sys.stdout.writelines(result)
return result
def add_name_and_surname(content, to_stdout=False):
result = add_surname(add_name(content))
if to_stdout is True:
sys.stdout.writelines(result)
return result
So I would like to make use of the two first functions as libraries, nothing to change here, but I'd also like to be able ot call those two functions as shell scripts which results could be piped:
$ echo "Here is my content" | add_name
Is there an pygical approach to do it? Would testing the to_stdout
variable make sense in the first place or is it error prone and inefficient?
I am also thinking about using the click
library to easily build commands from functions.
EDIT 2
Using the click
library the functions would look like this:
import click
import os, sys
@click.command()
@click.argument('content', required=False)
@click.option('--to_stdout', default=True)
def add_name(content, to_stdout=False):
if not content:
content = ''.join(sys.stdin.readlines())
result = content + "\n\tadded name"
if to_stdout is True:
sys.stdout.writelines(result)
return result
@click.command()
@click.argument('content', required=False)
@click.option('--to_stdout', default=True)
def add_surname(content, to_stdout=False):
if not content:
content = ''.join(sys.stdin.readlines())
result = content + "\n\tadded surname"
if to_stdout is True:
sys.stdout.writelines(result)
return result
@click.command()
@click.argument('content', required=False)
@click.option('--to_stdout', default=False)
def add_name_and_surname(content, to_stdout=False):
result = add_surname(add_name(content))
if to_stdout is True:
sys.stdout.writelines(result)
return result
This way I am able to generate the three commands "add_name", "add_surname" and "add_name_and_surname" using a setup.py
file and pip install --editable .
Then I am able to pipe:
$ echo "original content" | add_name | add_surname
original content
added name
added surname
However there is one slight problem I need to solve, when composing with different click
commands as functions:
$echo "original content" | add_name_and_surname
Usage: add_name_and_surname [OPTIONS] [CONTENT]
Error: Got unexpected extra arguments (r i g i n a l c o n t e n t
)
I have no idea why I get that result.