I am writing a program that performs different functions on the contents of a file. At the moment the file is stored in a variable and passed to each of the functions as such:
file = "path/to/file"
What I want to do is allow the user to enter the path using the command line function I have setup and have it passed to my functions.
However I am unsure on how to implement this into the command line file I have here
cli.py
import os, argparse
from . import parse
def validate_file(filename):
if not os.path.exists(filename):
raise argparse.ArgumentTypeError("{0} does not exist".format(filename))
return filename
def dump(filename):
for record in parse.uniprot_records(filename):
print(record)
...
(more function definitions)
...
def cli():
# Create a new parser
parser = argparse.ArgumentParser(description="UniProt Analysis")
# Input file
parser.add_argument("-i", "--input", dest="filename", type=validate_file, required=True, help="enter input file", metavar="FILE")
subparsers = parser.add_subparsers(help="Enter one of the arguments to run function")
# Add subparsers
subparsers.add_parser("dump", help="prints all records").set_defaults(func=dump)
# Parse the command line
args = parser.parse_args()
print(type(args.filename))
# Take the func argument, which points to our function and call it
args.func(args)
So I want to be able to pass the file and also have the function I want to perform on it in the command line e.g.
pipenv run python program.py path/to/file dump
Edit: Have added an argument to the parser to get the user's input file. This file is then passed into the dumpfunction, which passes the file into this function:
parse.py
import gzip
from Bio import SeqIO
def uniprot_records(f):
records = []
handle = gzip.open(f)
for record in SeqIO.parse(handle, "uniprot-xml"):
records.append(record)
return records
My main function is in a separate module where it simply calls the cli function. When I try to run this by doing pipenv run python uniplot.py -i path/to/file dump it gives me the following error:
File "/Users/john/workspace/practical-2/uniplot/parse.py", line 24, in uniprot_records handle = gzip.open(file_location)
File "/usr/local/Cellar/python/3.7.5/Frameworks/Python.framework/Versions/3.7/lib/python3.7/gzip.py", line 57, in open raise TypeError("filename must be a str or bytes object, or a file")
TypeError: filename must be a str or bytes object, or a file
dump should simply print out the entire contents of the given file after it has been unzipped using gzip.
Please use below syntax.
import argparse, os
from argparse import ArgumentParser
def validate_file(f):
if not os.path.exists(f):
# Argparse uses the ArgumentTypeError to give a rejection message like:
# error: argument input: x does not exist
raise argparse.ArgumentTypeError("{0} does not exist".format(f))
return f
if __name__ == "__main__":
parser = ArgumentParser(description="Read file form Command line.")
parser.add_argument("-i", "--input", dest="filename", required=True, type=validate_file,
help="input file", metavar="FILE")
args = parser.parse_args()
print(args.filename)
You can add arguments to the parser using parser.add_argument. These will be passed as a Namespace object to the called function:
import argparse
def dump(args):
print(args.path)
def cli():
# Create a new parser
parser = argparse.ArgumentParser()
subparsers = parser.add_subparsers()
parser.add_argument("path")
# Add subparsers
subparsers.add_parser("dump").set_defaults(func=dump)
# Parse the command line
args = parser.parse_args()
# Take the func argument, which points to the function and call it
args.func(args)
cli()
The command would look like:
python cli.py dump some/file
As for the recommended way of doing this, that will depend on your use-case. Passing all arguments to the script through the command-line will allow you to run the script more easily in some automated fashion than through interactive inputs. It will also allow you to rerun the same task more easily in a terminal. If that's not relevant for you than this is mostly a matter of personal preference.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With