Argparse File Output in Brackets and Single Quotes - python

Objective: To add a prefix or suffix to a string.
Problem: The output to the file is modified to include a [''] around the input. (ex: ['prefix']word, or word['suffix'])
Question: How do I remove the bracket and single quote around the input string?
Code:
parser.add_argument('-p', dest='prefix', metavar='[Prefix]', nargs=1, help="Add a user defined prefix")
parser.add_argument('-s', dest='suffix', metavar='[Suffix]', nargs=1, help="Add a user defined suffix")
#Adding a prefix to the string
elif args.prefix:
s = str(args.prefix)
print s
def addprefix(n):
p = s + n
args.outfile.write(p)
myline = args.infile.readline()
while myline:
addprefix(myline)
myline = args.infile.readline()
args.infile.close
#Adding a suffix to the string
elif args.suffix:
s = str(args.suffix)
def addsuf(n):
p = str(n.strip()+s+"\n")
args.outfile.write(p)
myline = args.infile.readline()
while myline:
addsuf(myline)
myline = args.infile.readline()
args.infile.close
Side Note: This is a snippet of code from the much larger program.
Thanks in advance.

I'm guessing the problem is nargs=1. This tells argparse that you want to make a list. Instead, remove the nargs=1 bit and put in action='store'. You may also want to specify a default.
parser.add_argument('-p', dest='prefix',
metavar='[Prefix]',action='store',default='',
help="Add a user defined prefix")

Related

Command-line argument overwritten by default value when using subparser

I have a program with sub commands, but they all have common arguments (e.g. they all require input and output directories) which I included in the parent parser to avoid redundancies. However, I want each subcommand to have a different default value, but this causes the value provided in the command-line to be ignored.
MWE:
import argparse
top_parser = argparse.ArgumentParser()
top_parser.add_argument("--input-dir", type=str)
subparsers = top_parser.add_subparsers()
generate_parser = subparsers.add_parser("generate")
generate_parser.set_defaults(input_dir=".")
process_parser = subparsers.add_parser("process")
process_parser.set_defaults(input_dir="SOME_OTHER_DIR")
generate_args = top_parser.parse_args("--input-dir USE_THIS_DIR generate".split())
print("generate_args = ", generate_args)
process_args = top_parser.parse_args("--input-dir USE_THIS_DIR process".split())
print("process_args = ", process_args)
This gives:
generate_args = Namespace(input_dir='.')
process_args = Namespace(input_dir='SOME_OTHER_DIR')
but I want:
generate_args = Namespace(input_dir='USE_THIS_DIR')
process_args = Namespace(input_dir='USE_THIS_DIR')
I can circumvent this by separately adding the argument to each subparser, but I would like to avoid this redundancy if possible.
One workaround would be to check the value of input_dir after parsing, and substitute a subparser-specific default at that time.
import argparse
top_parser = argparse.ArgumentParser()
top_parser.add_argument("--input-dir", type=str)
subparsers = top_parser.add_subparsers()
generate_parser = subparsers.add_parser("generate")
generate_parser.set_defaults(alt_input_dir=".")
process_parser = subparsers.add_parser("process")
process_parser.set_defaults(alt_input_dir="SOME_OTHER_DIR")
args = top_parser.parse_args()
if args.input_dir is None:
args.input_dir = args.alt_input_dir
del args.alt_input_dir

Python multiple user arguments to a list

I've got not words to thank you all of you for such great advice. Now everything started to make sense. I apologize for for my bad variable naming. It was just because I wanted to quickly learn and I wont carry out such practices when I write the final script with my own enhancements which will be posted here.
I want to go an another step further by passing the values we've isolated (ip,port,and name) to a template. I tried but couldn't get it right even though I feel close. The text I want to construct looks like this. (
Host Address:<IP>:PORT:<1>
mode tcp
bind <IP>:<PORT> name <NAME>
I have tried this within the working script provided by rahul.(I've edited my original code abiding stackexchange's regulations. Please help out just this once as well. Many thanks in advance.
#!/usr/bin/python
import argparse
import re
import string
p = argparse.ArgumentParser()
p.add_argument("input", help="input the data in format ip:port:name", nargs='*')
args = p.parse_args()
kkk_list = args.input
def func_three(help):
for i in help:
print(i)
for kkk in kkk_list:
bb = re.split(":|,", kkk)
XXX=func_three(bb)
for n in XXX:
ip, port, name = n
template ="""HOST Address:{0}:PORT:{1}
mode tcp
bind {0}:{1} name {2}"""
sh = template.format(ip,port,name)
print sh
orignial post:--
Beginner here. I wrote the below code and it doesn't get me anywhere.
#!/usr/bin/python
import argparse
import re
import string
p = argparse.ArgumentParser()
p.add_argument("INPUT")
args = p.parse_args()
KKK= args.INPUT
bb=re.split(":|,", KKK)
def func_three(help):
for i in help:
#print help
return help
#func_three(bb[0:3])
YY = var1, var2, var3 = func_three(bb[0:3])
print YY
The way to run this script should be "script.py :". i.e: script.py 192.168.1.10:80:string 172.25.16.2:100:string
As you can see if one argument is passed I have no problems. But when there are more arguments I cant determine how to workout the regexes and get this done via a loop.
So to recap, this is how i want the output to look like to proceed further.
192.168.1.10
80
name1
172.25.16.2
100
name2
If there are better other ways to achieve this please feel free to suggest.
I would say what you are doing could be done more simply. If you want to split the input whenever a colon appears you could use:
#!/usr/bin/python
import sys
# sys.argv is the list of arguments you pass when you run the program
# but sys.argv[0] is the actual program name
# so you want to start at sys.argv[1]
for arg in sys.argv[1:]:
listVar = arg.split(':')
for i in listVar:
print i
# Optionally print a new line
print
Please name your variable with respect to context. You will need to use nargs=* for accepting multiple arguments. I have added the updated code below which prints as you wanted.
#!/usr/bin/python
import argparse
import re
import string
p = argparse.ArgumentParser()
p.add_argument("input", help="input the data in format ip:port:name", nargs='*')
args = p.parse_args()
kkk_list = args.input # ['192.168.1.10:80:name1', '172.25.16.2:100:name3']
def func_three(help):
for i in help:
print(i)
for kkk in kkk_list:
bb = re.split(":|,", kkk)
func_three(bb)
print('\n')
# This prints
# 192.168.1.10
# 80
# name1
# 172.25.16.2
# 100
# name3
Updated Code for new requirement
#!/usr/bin/python
import argparse
import re
import string
p = argparse.ArgumentParser()
p.add_argument("input", help="input the data in format ip:port:name", nargs='*')
args = p.parse_args()
kkk_list = args.input # ['192.168.1.10:80:name1', '172.25.16.2:100:name3']
def printInFormat(ip, port, name):
formattedText = '''HOST Address:{ip}:PORT:{port}
mode tcp
bind {ip}:{port} name {name}'''.format(ip=ip,
port=port,
name=name)
textWithoutExtraWhitespaces = '\n'.join([line.strip() for line in formattedText.splitlines()])
# you can break above thing
# text = ""
# for line in formattedText.splitlines():
# text += line.strip()
# text += "\n"
print(formattedText)
for kkk in kkk_list:
ip, port, name = re.split(":|,", kkk)
printInFormat(ip, port, name)
# HOST Address:192.168.1.10:PORT:80
# mode tcp
# bind 192.168.1.10:80 name name1
# HOST Address:172.25.16.2:PORT:100
# mode tcp
# bind 172.25.16.2:100 name name3
Bad variable names aside, if you want to use argparse (which I think is a good habit, even if it is somewhat more complex initially) you should use the nargs='+' option:
#!/usr/bin/env python
import argparse
import re
import string
p = argparse.ArgumentParser()
p.add_argument("INPUT", nargs='+')
args = p.parse_args()
KKK= args.INPUT
def func_three(help):
for i in help:
#print help
return help
for kkk in KKK:
bb=re.split(":|,", kkk)
#func_three(bb[0:3])
YY = var1, var2, var3 = func_three(bb[0:3])
print YY
If you look at the documentation for argparse, you'll notice that there's an nargs argument you can pass to add_argument, which allows you to group more than one input.
For example:
p.add_argument('INPUT', nargs='+')
Would make it so that there is a minimum of one argument, but all arguments will be gathered into a list.
Then you can go through each of your inputs like this:
args = p.parse_args()
for address in args.INPUT:
ip, port = address.split(':')

Is there an other way to parse args with groups?

I just tried those:
arg = argparse.ArgumentParser(description='Corpse v0.1a Stable Alpha Experiment')
arg.add_argument('--about', help = 'About author and license information.', action = 'store_true')
gr_root = arg.add_mutually_exclusive_group()
gr_render = gr_root.add_mutually_exclusive_group()
gr_render.add_argument('-r', '--render', help = 'A raw text to render it into a corpus database.')
gr_render.add_argument('--append', help = 'If there is already a database, this option will be useful.', action = 'store_true')
gr_load = gr_root.add_mutually_exclusive_group()
gr_load.add_argument('-l', '--load', help = 'A database name to report the content.')
gr_load.add_argument('-p', '--pattern', help = 'The token pattern that is needed to be reported.')
gr_load.add_argument('--less', help = 'List the pattern that is "less and equal" than the count.', action = 'store')
gr_load.add_argument('--more', help = 'List the pattern that is "more and equal" than the count.', action = 'store')
args = vars(arg.parse_args())
I used a question in this platform, but I do not remember which it is. When I use add_mutually_exclusive_group(), it seems it seperates group arguments with "OR" operator. I understand it with this output I get:
usage: corpse.py [-h] [--about] [[-r RENDER | --append]
[-l LOAD | -p PATTERN | --less LESS | --more MORE]
corpse.py: error: argument --append: not allowed with argument -r/--render
However, I want to seperate arguments to the groups to use them together which means I want this:
[-r RENDER & --append]
Not this:
[-r RENDER | --append]
I mean I use render and append argument together and not with load, pattern, less and more.
http://bugs.python.org/issue22047 explains your difficulty with nested groups. Note the [[ in the usage.
Your best bet for now is to test after parsing. See https://stackoverflow.com/a/24915802/901925.
What would the ideal usage line look like?
Here's a rough sketch of a subparser based solultion:
parser = ArguementParser()
sp = parser.add_subparsers(dest='cmd')
sp.add_parser('about')
spp = sp.add_parser('load', help='report content of a database')
spp.add_argument('database')
spp.add_argument('--pattern', ...)
spp.add_argument('--less', ...)
spp.add_argument('--more', ...)
spp = sp.add_parser('render', help='render text into a database')
spp.add_argument('text')
spp.add_argument('--append',...)

Python counting the unique occurences of a string in a file

I’m trying to count the unique IP addresses in a Apache log-file using python 3.3.1
The thing is I don’t think that it is counting everything correctly.
Here is my code:
import argparse
import os
import sys
from collections import Counter
#
# This function counts the unique IP adresses in the logfile
#
def print_unique_ip(logfile):
IPset = set()
for line in logfile:
head, sep, tail = line.partition(" ")
if(len(head) > 1):
IPset.update(head)
print(len(IPset))
return
#
# This is the main function of the program
#
def main():
parser = argparse.ArgumentParser(description="An appache log file processor")
parser.add_argument('-l', '--log-file', help='This is the log file to work on', required=True)
parser.add_argument('-n', help='Displays the number of unique IP adresses', action='store_true')
parser.add_argument('-t', help='Displays top T IP adresses', type=int)
parser.add_argument('-v', help='Displays the number of visits of a IP adress')
arguments = parser.parse_args()
if(os.path.isfile(arguments.log_file)):
logfile = open(arguments.log_file)
else:
print('The file <', arguments.log_file, '> does not exist')
sys.exit
if(arguments.n == True):
print_unique_ip(logfile)
if(arguments.t):
print_top_n_ip(arguments.t, logfile)
if(arguments.v):
number_of_ocurrences(arguments.v, logfile)
return
if __name__ == '__main__':
main()
I have left put everything else.
When I run it I get
$ python3 assig4.py -l apache_short.log -n
12
But I know that there are more than 12 unique IPs in the file
It doesn’t seem to be giving me the right result. What I am trying to do is to read the file line by line, then when I find an IP address I put it into a set as it only saves unique elements and then I print out the length of said set.
IPset.update(head)
Bug. This will not do what you're expecting. You want to add each IP to your set instead. Examples make it clearest:
>>> s1 = set()
>>> s2 = set()
>>> s1.add('11.22.33.44')
>>> s2.update('11.22.33.44')
>>> s1
set(['11.22.33.44'])
>>> s2
set(['1', '3', '2', '4', '.'])

Editing text file through command line argument in Python

I want to edit text file by passing integer number via command line argument in Python. However my code is not working, can some one point me where I am wrong.
import sys, argparse
def main(argv=None):
if argv is None:
argv=sys.argv[1:]
p = argparse.ArgumentParser(description="Editing omnetpp.ini")
p.add_argument('arg1', action='store', default= 1, type=int, help="number of clients")
args = p.parse_args(argv)
n = args.arg1
f = open('C:\\Users\Abcd\Desktop\Omnet\omnetpp.ini', 'a')
for i in range(n):
f.write('*.voipClient['+str(i)+'].udpApp['+str(i)+'].destAddresses = "voipGateway"\n')
f.write('*.voipGateway.udpApp['+str(i)+'].destAddresses = "voipClient['+str(i)+']"\n')
f.close()
If integer number 5 is passed via command line argument then it should add following lines in text file, which is not happening
Output
*.voipClient[0].udpApp[0].destAddresses = "voipGateway"
*.voipGateway.udpApp[0].destAddresses = "voipClient[0]"
*.voipClient[1].udpApp[1].destAddresses = "voipGateway"
*.voipGateway.udpApp[1].destAddresses = "voipClient[1]"
*.voipClient[2].udpApp[2].destAddresses = "voipGateway"
*.voipGateway.udpApp[2].destAddresses = "voipClient[2]"
*.voipClient[3].udpApp[3].destAddresses = "voipGateway"
*.voipGateway.udpApp[3].destAddresses = "voipClient[3]"
*.voipClient[4].udpApp[4].destAddresses = "voipGateway"
*.voipGateway.udpApp[4].destAddresses = "voipClient[4]"
I am following these steps:
Code is saved in test.py
From command line C:\Users\Abcd\Desktop>python test.py 5
Don't close the file in the loop, as soon as it is closed you cannot write to it anymore (in fact, an error should be thrown if you try to write to a closed file object).
Instead, close it after the loop.
Also, to put each sentence on a new line, end the string with the newline symbol \n (sort of pressing "ENTER").
f = open('C:\\Users\Abcd\Desktop\Omnet\omnetpp.ini', 'a')
for i in range(n):
f.write('*.voipClient['+str(i)+'].udpApp['+str(i)+'].destAddresses = "voipGateway"\n')
f.write('*.voipGateway.udpApp['+str(i)+'].destAddresses = "voipClient['+str(i)+']"\n')
f.close()
EDIT
By the way, as Rostyslav Dzinko said in the comments, the way you defined your code is not how you define a main function. In fact, try something like this (see also this SO question):
if __name__ == '__main__':
p = argparse.ArgumentParser(description="Editing omnetpp.ini")
p.add_argument('arg1', action='store', default= 1, type=int, help="number of clients")
args = p.parse_args()

Categories

Resources