I have tried the below code
def parse_args():
"""Get user command line parameters"""
parser = argparse.ArgumentParser(description="Available Options")
parser.add_argument('-i', '--input-path', type=is_valid_path,
required=True, help="Enter the path of the file or the folder to process")
parser.add_argument('-a', '--action', choices=[
'Highlight', 'Redact'], type=str, help="Choose to highlight or to redact")
parser.add_argument('-s', '--search-str', dest='search_str',
type=str, help="Enter a valid search string")
parser.add_argument('-p', '--pages', dest='pages', type=tuple,
help="Enter the pages to consider in the PDF file, e.g. (0,1)")
parser.add_argument("-g", "--generate-output", action="store_true", help="Generate text content in a CSV file")
path = parser.parse_known_args()[0].input_path
if os.path.isfile(path):
parser.add_argument('-o', '--output_file', dest='output_file',
type=str, help="Enter a valid output file")
parser.add_argument("-t", "--highlight-readable-text", action="store_true", help="Highlight readable text in the generated image")
parser.add_argument("-c", "--show-comparison", action="store_true", help="Show comparison between captured image and the generated image")
if os.path.isdir(path):
parser.add_argument("-r", "--recursive", action="store_true", help="Whether to process the directory recursively")
# To Porse The Command Line Arguments
args = vars(parser.parse_args())
# To Display The Command Line Arguments
print("## Command Arguments #################################################")
print("\n".join("{}:{}".format(i, j) for i, j in args.items()))
print("######################################################################")
return args
if name == 'main':
args = parse_args()
# If File Path
if os.path.isfile(args['input_path']):
# Process a file
if filetype.is_image(args['input_path']):
ocr_img(
# if 'search_str' in (args.keys()) else None
img=None, input_file=args['input_path'], search_str=args['search_str'], highlight_readable_text=args['highlight_readable_text'], action=args['action'], show_comparison=args['show_comparison'], generate_output=args['generate_output']
)
else:
ocr_file(
input_file=args['input_path'], output_file=args['output_file'], search_str=args['search_str'] if 'search_str' in (args.keys()) else None, pages=args['pages'], highlight_readable_text=args['highlight_readable_text'], action=args['action'], show_comparison=args['show_comparison'], generate_output=args['generate_output']
)
# If Folder Path
elif os.path.isdir(args['input_path']):
# Process a folder
ocr_folder(
input_folder=args['input_path'], recursive=args['recursive'], search_str=args['search_str'] if 'search_str' in (args.keys()) else None, pages=args['pages'], action=args['action'], generate_output=args['generate_output']
)
Getting this error
usage: ipykernel_launcher.py [-h] -i INPUT_PATH [-a {Highlight,Redact}]
[-s SEARCH_STR] [-p PAGES] [-g]
ipykernel_launcher.py: error: the following arguments are required: -i/--input-path
An exception has occurred, use %tb to see the full traceback.
SystemExit: 2
C:\Users\poddaral\AppData\Roaming\Python\Python310\site-packages\IPython\core\interactiveshell.py:3386: UserWarning: To exit: use 'exit', 'quit', or Ctrl-D.
warn("To exit: use 'exit', 'quit', or Ctrl-D.", stacklevel=1)
You need to paas input path as an argument while running the code. Let's say file name is abc.py, then in command line run
python abc.py --input_path Path
Related
I have a command line application that can accept either the command line argument --input_files or --unigrams, but not both at the same time:
import click
import pathlib
from typing import Optional
#click.command()
#click.option(
"--input_files",
default=None,
type=str,
help="Comma-separated list of one-sentence-per-line raw corpus files",
)
#click.option("--unigrams", default=None, type=str, help="Comma-separated list of unigrams")
#click.option(
"--model_path",
default="spm/models",
type=click.Path(file_okay=False, path_type=pathlib.Path),
help="Output model path",
)
def minimal(
model_path: pathlib.Path,
input_files: Optional[str],
unigrams: Optional[str]
) -> str:
if input_files and unigrams:
raise ValueError("Only one of input_files or unigrams can be specified.")
if input_files:
click.echo(f"input_files: {input_files}")
if unigrams:
click.echo(f"Unigrams: {unigrams}")
I wrote a test for the case where both arguments are passed, using file system isolation, and expect the ValueError to be raised:
from click.testing import CliRunner
def test_minimal(tmp_path: str) -> None:
runner = CliRunner()
with runner.isolated_filesystem(temp_dir=tmp_path):
result = runner.invoke(
minimal,
["--model_path", tmp_path, "--input-files", "test.txt", "--unigrams", "a,b"],
)
assert isinstance(result.exception, ValueError)
assert "Only one of input_files or unigrams can be specified." in str(result.exception)
but this test fails because a SystemExit is raised:
=================================================================================== FAILURES ====================================================================================
_________________________________________________________________________________ test_minimal __________________________________________________________________________________
tmp_path = PosixPath('/tmp/pytest-of-biogeek/pytest-2/test_minimal0')
def test_minimal(tmp_path: str) -> None:
runner = CliRunner()
with runner.isolated_filesystem(temp_dir=tmp_path):
result = runner.invoke(
train_spm.minimal,
["--model_path", tmp_path, "--input-files", "test.txt", "--unigrams", "a,b"],
)
> assert isinstance(result.exception, ValueError)
E assert False
E + where False = isinstance(SystemExit(2), ValueError)
E + where SystemExit(2) = <Result SystemExit(2)>.exception
stackoverflow_test.py:20: AssertionError
============================================================================ short test summary info ============================================================================
FAILED projects/stackoverflow_test.py::test_minimal - assert False
What am I doing wrong?
SystemExit(2) is a UsageError as referenced by this answer. This means that something is likely incorrect in the command line script.
When inspecting the original file, you define the argument flag as --input_files. However, the test script is invoking --input-files.
Replacing the dash with an underscore fixes your issue and the test passes.
Here is the code.
def main():
parser = argparse.ArgumentParser(
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
description="infomedia"
)
parser.add_argument("file", help="path to file")
parser.add_argument(
"-i",
"--info",
type=str,
default="False",
help="get information about",
)
cli_args = parser.parse_args()
worker = Worker(
cli_args.input,
cli_args.info,
)
worker._application()
When the program is running with -h / --help it shows the default values.
positional arguments:
file path to file
optional arguments:
-h, --help show this help message and exit
-i INFO, --info INFO get information about (default: False)
How to avoid printing the default values? Or is there a way to define the default values of this code in a different way?
You can create new class inheriting from argparse.ArgumentDefaultsHelpFormatter and override _get_help_string method and pass your newly created class which is MyHelpFormatter in the below example as formatter_class in ArgumentParser constructor. Here is the example code which can help you:
import argparse
class MyHelpFormatter(argparse.ArgumentDefaultsHelpFormatter):
def _get_help_string(self, action):
return action.help
def main():
parser = argparse.ArgumentParser(
formatter_class=MyHelpFormatter,
description="infomedia",
)
parser.add_argument("file", help="path to file")
parser.add_argument(
"-i",
"--info",
type=str,
default="False",
help="get information about",
)
cli_args = parser.parse_args()
if __name__ == "__main__":
main()
I think you want more like:
parser.add_argument("--info", help="get information", action="store_true")
I want to implement a python3 command line by argparse, which supports positional arguments and flag options.
For example:
usage: mycmd [-v] [-h] [-o] text
mycmd text print text
mycmd -h show help message and exit
mycmd -v show version info
mycmd -o text print text and dump text to file mycmd.txt
Here's my implementation:
import argparse
class MyCmd:
def __init__(self):
self.parser = argparse.ArgumentParser()
self.parser.add_argument('text', help='print text') # mycmd text
self.parser.add_argument('-v', action='store_true', dest='version', help='show version info') # mycmd -v
self.parser.add_argument('-o', dest='output', help='print text and dump text to file mycmd.txt')
def parse(self):
return self.parser.parse_args()
def text(self, text):
print(text)
def version(self):
print('version info: mycmd-0.0.1')
def output(self, text):
print(text)
fp = open('mycmd.txt', 'w')
fp.write(text + '\n')
fp.close()
if __name__=='__main__':
mycmd = MyCmd()
(options, args) = mycmd.parse()
if options.text is not None:
mycmd.text(text)
elif options.version is not None:
mycmd.version()
elif options.output is not None:
mycmd.output(options.output)
When I test it with:
$ ./mycmd -v
Gives me error:
usage: mycmd [-h] [-o OUTPUT]
[-v]
text
mycmd: error: the following arguments are required: text
Why mycmd cannot consume mycmd -v ?
What your original implementation is missing is the step of including a specific subparse to the text processing flow.
Here's a more simplified version (without a class):
import argparse
def version():
return 'v0.0.1'
def print_and_save(text, file_path):
print(text)
if file_path:
with open(file_path, 'w') as fp:
fp.write(text + '\n')
fp.close()
if __name__=='__main__':
# Root (rt)
root_parser = argparse.ArgumentParser()
root_parser.add_argument('-v', '--version', action='store_true', help='show version info')
root_sbparsers = root_parser.add_subparsers(help='sub-command help')
# Adding sub-commands
text_parser = root_sbparsers.add_parser('process', help='print text')
text_parser.add_argument('text', type=str, help='text you want to work with')
text_parser.add_argument('-o', type=str, default=None, help='print text and dump text to file mycmd.txt')
args = root_parser.parse_args()
if args.version:
print(version())
elif args.text:
print_and_save(args.text, args.o)
I'm not sure why you have to embed it on a whole class but here's the version with it:
import argparse
class MyCmd(object):
def __init__(self):
# Root (rt)
self.parser = argparse.ArgumentParser()
self.parser.add_argument('-v', '--version', action='store_true', help='show version info')
root_sbparsers = self.parser.add_subparsers(help='sub-command help')
# Adding sub-commands
text_parser = root_sbparsers.add_parser('process', help='print text')
text_parser.add_argument('text', type=str, help='text you want to work with')
text_parser.add_argument('-o', type=str, default=None, help='print text and dump text to file mycmd.txt')
def parse(self):
return self.parser.parse_args()
def text(self, text):
print(text)
def version(self):
print('version info: mycmd-0.0.1')
def output(self, text, file_path):
with open(file_path, 'w') as fp:
fp.write(text + '\n')
fp.close()
if __name__=='__main__':
mycmd = MyCmd()
args = mycmd.parse()
if args.version:
mycmd.version()
elif args.text:
mycmd.text(args.text)
if args.o:
mycmd.output(args.text, args.o)
I'm running Python 3.6.8 :: Anaconda custom (64-bit) and getting strange results from argparse. Despite the -x, the value of trainandexecute=False
def get_parameters():
startup = '-x -b'
sys.argv = startup.split(' ')
ap = argparse.ArgumentParser()
ap.add_argument('-x', '--trainandexecute', action='store_true')
ap.add_argument('-b', '--debug', action='store_true')
ap.add_argument('-d', '--rundate', action='store')
print(ap.parse_args())
return vars(ap.parse_args())
get_parameters()
This returns the following output. Notet that trainandexecute=False despite the -x flag.
Namespace(debug=True, execute=False, train=False, trainandexecute=False)
{'train': False,
'execute': False,
'trainandexecute': False,
'debug': True}
However, this test works in the next Jupyter cell and that it is not my environment:
def get_test_parameters():
startup = '-b -x'
sys.argv = startup.split(' ')
print(sys.argv)
ap = argparse.ArgumentParser()
ap.add_argument('-x', '--x', action='store_true')
ap.add_argument('-b', '--debug', action='store_true')
print(ap.parse_args())
return vars(ap.parse_args())
So the output of:
get_test_parameters()
is:
['-b', '-x'] # print(sys.argv)
Namespace(debug=False, x=True) # print(ap.parse_args())
{'x': True, 'debug': False} # return vars(ap.parse_args())
I'm bifflesnickered...
Your error is in this line:
sys.argv = startup.split(' ')
The first value in sys.argv is treated as the name of the script, not as an option. Try running ap.parse_args(startup.split()) - and you will see the right answer.
Incidentally, do not pass any parameters to split(). If you pass " " and you have more than one consecutive space, the result of the split will have empty strings.
Here's a better test framework:
def get_parameters(argv=None):
ap = argparse.ArgumentParser()
ap.add_argument('-x', '--trainandexecute', action='store_true')
ap.add_argument('-b', '--debug', action='store_true')
ap.add_argument('-d', '--rundate', action='store')
args = ap.parse_args(argv)) # if None, parses sys.argv[1:]
print(args)
return vars(args)
get_parameters('-x -b'.split())
You can modify sys.argv[1:] instead. By passing argv through your function, you can test several ways.
I need to rewrite an arguments parser.The application has two modes: console and graphics. We can choose only one mode. Lately, the console version received two arguments: name of file with text and name of file with words. It looked so:
def parse_args():
parser = argparse.ArgumentParser(description='Fuzzy search in text')
parser.add_argument('-g', '--graphics', help='graphical version',
action='store_true')
parser.add_argument('-c', '--console', help='console version', nargs=2,
type=argparse.FileType('r'),
metavar=('TEXTFILE', 'WORDSFILE'))
return parser.parse_args()
usage: fuzzy_search.py [-h] [-g] [-c TEXTFILE WORDSFILE]
Fuzzy search in text
optional arguments:
-h, --help show this help message and exit
-g, --graphics graphical version
-c TEXTFILE WORDSFILE, --console TEXTFILE WORDSFILE
console version
Now I need to rewrite the accepting of arguments in the console version. I want to add two optional arguments that will store true for register-sensitivity (-r) and special view(-v). I know how to do it but I can't understand what to do with the next thing. I want to make two variants: 1)obligatory two files with text and words like it was initially and 2) obligatory file with text and not obligatory file with words, if it's not written than default - sys.stdin. Graphics shouldn't accept any arguments. So it should look like this
usage: fuzzy_search.py [-h] [-g] [-c [-r] [-v] TEXTFILE WORDSFILE(if not written then sys.stdin)]
I tried this variant:
parser = argparse.ArgumentParser()
subparsers = parser.add_subparsers(help='versions')
parser_console = subparsers.add_parser('console', help='console version')
parser_console.add_argument('-r', '--register-check', action='store_true', help='register sensitivity')
parser_console.add_argument('-v', '--row-view', action='store_true', help='row view')
parser_console.add_argument('TEXTFILE', type=argparse.FileType('r'), help='text file')
parser_console.add_argument('--WORDSFILE', type=argparse.FileType('r'), default=sys.stdin, help='words file')
parser_graphics = subparsers.add_parser('graphics', help='graphics version')
But when I tried this
print(parser.parse_args(['console', '-r', '-v', 'text.txt','words.txt']))
there was an error:
unrecognized arguments: words.txt
with this
print(parser.parse_args(['console', '-r', '-v', 'text.txt']))
everything is ok:
Namespace(TEXTFILE=<_io.TextIOWrapper name='text.txt' mode='r' encoding='cp1251'>, WORDSFILE=<_io.TextIOWrapper name='<stdin>' mode='r' encoding='UTF-8'>, register_check=True, row_view=True)
So problem somewhere in optional argument WORDSFILE and its default value. How to correct it?
Use -t for text and -w for the words file. The latter with default:
import argparse
parser = argparse.ArgumentParser()
subparsers = parser.add_subparsers(help='versions')
parser_console = subparsers.add_parser('console',
help='console version')
parser_console.add_argument('-r', '--register-check',
action='store_true', help='register sensitivity')
parser_console.add_argument('-v', '--row-view',
action='store_true', help='row view')
parser_console.add_argument('-t', '--textfile',
type=argparse.FileType('r'),
help='text file')
parser_console.add_argument('-w', '--wordsfile', type=argparse.FileType('r'),
default=sys.stdin, help='words file')
print(parser.parse_args(['console', '-r', '-v', '-t', 'text.txt',
'-w', 'words.txt']))
parser.parse_args(['console', '-r', '-v', '-t', 'text.txt'])
Output:
Namespace(register_check=True, row_view=True,
textfile=<_io.TextIOWrapper name='text.txt' mode='r' encoding='UTF-8'>,
wordsfile=<_io.TextIOWrapper name='words.txt' mode='r' encoding='UTF-8'>)
Namespace(register_check=True, row_view=True,
textfile=<_io.TextIOWrapper name='text.txt' mode='r' encoding='UTF-8'>,
wordsfile=<_io.TextIOWrapper name='<stdin>' mode='r' encoding='UTF-8'>)