3

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.

kaligne
  • 3,098
  • 9
  • 34
  • 60

0 Answers0