Error handling with verbose output - python

Im trying to implement the --verbose option in my script. The idea is to turn on extra printing of errors etc for debugging, but for some reason it doesnt seem to work. Ive tried a few variations of the if verbose statement but no joy. Im hoping someone could point me in the right direction?
CLI EXAMPLE
./attack2.py -f wordfile.txt -d google.com --verbose 1
CLI OUTPUT
unknown#ubuntu:~$ ./attack2.py -f wordfile.txt -d google.com --verbose 1
173.194.34.149
173.194.34.130
unknown#ubuntu:~$
ARG PRINT
{'--domain': 'google.com',
'--file': 'wordfile.txt',
'--help': False,
'--thread': False,
'--verbose': True,
'10': False,
'<1>': '1'}
CODE
#!/usr/bin/python
"""
Description:
Basic Domain bruteforcer
Usage:
attack2.py (-f <file>) (-d <domain>) [-t 10] [-v <1>]
attack2.py -h | --help
Arguments:
-f --file File to read potential Sub-domains from. (Required)
-d --domain Domain to bruteforce. (Required)
Options:
-h --help Show this screen.
-p --proxy Proxy address and port. [default: http://127.0.0.1:8080] (Optional)
-t --thread Thread count. (Optional)
-v --verbose Turn debug on. (Optional)
"""
import socket
from docopt import docopt
def fread(dwords):
flist = open(dwords).readlines()
return [s.replace('\n', '.') for s in flist]
def subcheck(subdomain, domain, verbose):
vdomain = {}
for sub in subdomain:
try:
check = socket.gethostbyname(sub + domain)
vdomain[sub + domain] = check
except socket.gaierror, e:
if verbose == True:
print arguments
print e, sub + domain
else:
pass
return vdomain
if __name__ == "__main__":
arguments = docopt(__doc__, version='0.1a')
fread(arguments['--file'])
returned_list = fread(arguments['--file'])
returned_domains = subcheck(returned_list, arguments['--domain'], ['--verbose'])

The below line in function subcheck
returned_domains = subcheck(returned_list, arguments['--domain'], ['--verbose'])
should be
returned_domains = subcheck(returned_list, arguments['--domain'], arguments['--verbose'])
You forgot to pass the verbose param from arguments, instead you passed a list

It seems I was calling the subcheck incorrectly.
Code should have looked like this
Working CODE
if __name__ == "__main__":
arguments = docopt(__doc__, version='0.1a')
fread(arguments['--file'])
returned_list = fread(arguments['--file'])
returned_domains = subcheck(returned_list, arguments['--domain'], arguments['--verbose'])
print returned_domains

Related

Argparse: either (x and y) OR (z)

I have the following code:
def main():
argParser = argparse.ArgumentParser(description = 'DESCRIPTION',epilog = 'Please see README.MD for guidance on how to use this script')
argParser.add_argument('-i', '--inFile', action='store',type=str, required = True, help = 'Input config file')
argParser.add_argument('-o', '--outFile', action = 'store', default = sys.stdout, type = argparse.FileType('w'), required = False, help = 'Output VCD File')
# generate_config_group = argParser.add_mutually_exclusive_group()
argParser.add_argument('-g', '--generate-config', action='store_true',help='Generate empty config File to fill')
args = argParser.parse_args()
print("\nExecuting Script:" + str(sys.argv[0]))
print(" config file:" + str(args.inFile))
print(" vcd outFile:" + str(args.outFile.name))
if args.generate-config:
if generate_config():
return 'config generated. see sample-config.ini. You will need to edit these values for this script to run successfully'
I want it so that you either need BOTH -i and -o arguments OR the -g argument. Right now if you supply -g, it still gets mad that you haven't supplied -i and -o. What is the way to do this? I have heard subparsers might be the way, but I see that with those, you call the command differently - script.py subparser_name -flags.
I don't want that. I only want -o and -i and -g as possible flags.
Why not update the IF at the end to something like:
import warnings
if (args.generate-config) or (args.inFile and args.outFile):
if generate_config():
return 'config generated. see sample-config.ini. You will need to edit these values for this script to run successfully'
else:
warnings.warn("When executing script i and o or g are required.")

docopt boolean arg python

I use following args for my script with doctopt
Usage:
GaussianMixture.py --snpList=File --callingRAC=File
Options:
-h --help Show help.
snpList list snp txt
callingRAC results snp
I would like to add an argument that have a conditional consequence on my script : correct my datas or don't correct my datas. Something like :
Usage:
GaussianMixture.py --snpList=File --callingRAC=File correction(--0 | --1)
Options:
-h --help Show help.
snpList list snp txt
callingRAC results snp
correction 0 : without correction | 1 : with correction
And I would like to add in my script an if in some functions
def func1():
if args[correction] == 0:
datas = non_corrected_datas
if args[correction] == 1:
datas = corrected_datas
But I don't know how to write it in the usage neither in my script.
EDIT:
My original answer didn't take into account OP's requirements for --correction to be mandatory. Syntax was incorrect in my original answer. Here's a tested working example:
#!/usr/bin/env python
"""Usage:
GaussianMixture.py --snpList=File --callingRAC=File --correction=<BOOL>
Options:
-h, --help Show this message and exit.
-V, --version Show the version and exit
--snpList list snp txt
--callingRAC results snp
--correction=BOOL Perform correction? True or False. [default: True]
"""
__version__ = '0.0.1'
from docopt import docopt
def main(args):
args = docopt(__doc__, version=__version__)
print(args)
if args['--correction'] == 'True':
print("True")
else:
print("False")
if __name__ == '__main__':
args = docopt(__doc__, version=__version__)
main(args)
Please let me know if this works for you.
Not all options have to have arguments in docopt. In other words, you can use flag arguments instead. This is the most straightforward way to get boolean values from a user. That being said, you can simply do the following.
"""
Usage:
GaussianMixture.py (--correction | --no-correction)
Options:
--correction With correction
--no-correction Without correction
-h --help Show help.
"""
import docopt
if __name__ == '__main__':
args = docopt.docopt(__doc__)
print(args)

Concatenating list items with string

I'm taking a list generated from reading a file and trying to take each item and concatenating it to another input string. I can understand the error; I can't concat a list item with a string. But how do I convert each item from the list into a string. I tried ' '.join(list) but that didn't work either.
I'm getting the following error:
ERROR
Traceback (most recent call last):
File "./attack2.py", line 40, in <module>
print subcheck(returned_list, ['--domain'])
File "./attack2.py", line 31, in subcheck
socket.gethostbyname(sub + domain)
TypeError: cannot concatenate 'str' and 'list' objects
CODE
#!/usr/bin/python
"""
Description:
Basic Domain bruteforcer
Usage:
attack2.py (-f <file>) (-d <domain>) [-t 10] [-v]
attack2.py -h | --help
Arguments:
-f --file File to read potential Sub-domains from. (Required)
-d --domain Domain to bruteforce. (Required)
Options:
-h --help Show this screen.
-p --proxy Proxy address and port. [default: http://127.0.0.1:8080] (Optional)
-t --thread Thread count. (Optional)
-v --verbose Turn debug on. (Optional)
"""
import socket
from docopt import docopt
def fread(dwords):
flist = open(dwords).readlines()
return [s.replace('\n', '.') for s in flist]
def subcheck(subdomain, domain):
for sub in subdomain:
socket.gethostbyname(sub + domain)
return output
if __name__ == "__main__":
arguments = docopt(__doc__, version='0.1a')
print arguments
print fread(arguments['--file'])
returned_list = fread(arguments['--file'])
print subcheck(returned_list, ['--domain'])
print subcheck(returned_list, ['--domain'])
Did you mean to retrieve the domain option from the arguments object?
print subcheck(returned_list, arguments['--domain'])

Removing newline characters not working

Im trying to remove the \n from a list created in a function. My code for removing it doesnt seem to be working. Im not getting an error either??
CODE
#!/usr/bin/python
"""
Description:
Basic Domain bruteforcer
Usage:
your_script.py (-f <file>) (-d <domain>) [-t 10] [-v]
your_script.py -h | --help
Arguments:
-f --file File to read potential Sub-domains from. (Required)
-d --domain Domain to bruteforce. (Required)
Options:
-h --help Show this screen.
-p --proxy Proxy address and port. [default: http://127.0.0.1:8080] (Optional)
-t --thread Thread count. (Optional)
-v --verbose Turn debug on. (Optional)
"""
from docopt import docopt
def fread(dwords, *args):
flist = open(dwords).readlines()
#print current list
print flist
nlist = flist
for i in nlist:
i.rstrip('\n')
return nlist
if __name__ == "__main__":
arguments = docopt(__doc__, version='0.1a')
# print new list with removed \n
print fread(arguments['--file'])
Strings are not mutable, i.rstrip('\n') returns a new string.
Use a list comprehension:
def fread(dwords):
flist = open(dwords).readlines()
return [s.rstrip('\n') for s in flist]
or, since you are reading the whole file into memory anyway, str.splitlines():
def fread(dwords):
return open(dwords).read().splitlines()

getopt() not enforcing required arguments?

I'm having problems with this getopt() code in a script that I'm writing which does some simple file manipulation given 2 required parameters (input filename and output filename) and/or 2 optional/situational arguments (debug or help).
Code is:
def main(argv):
try:
opts, args = getopt.getopt(argv, "i:o:dh", ["input-file=", "output-file=", "debug", "help"])
except getopt.GetoptError:
usage()
sys.exit(2)
for opt, arg in opts:
if opt in ("-h", "--help"):
usage()
sys.exit()
elif opt in ("-d", "--debug"):
global _debug
_debug = 1
elif opt in ("-i", "--input-file"):
u_input_file_name = arg
elif opt in ("-o", "--output-file"):
u_output_file_name = arg
According to the getopt() documentation:
options that require an argument followed by a colon (':'; i.e., the same format that Unix getopt() uses).
The problem is that as I understand it, the variables/args followed by a : should be enforced as required ... but the options i and o are not being enforced. Running this snippet garners an error about u_input_file_name being referenced before being assigned:
[tdelane#fbsd81-1 ~/python]$ ./inco_add_cm_mpscli.py -o google
Traceback (most recent call last):
File "./inco_add_cm_mpscli.py", line 57, in <module>
main(sys.argv[1:])
File "./inco_add_cm_mpscli.py", line 25, in main
infile = open(u_input_file_name, 'r')
UnboundLocalError: local variable 'u_input_file_name' referenced before assignment
What am I doing wrong?
An option followed by a colon only means that it needs an argument. It doesn't mean that the option is enforced. You should write your own code to enforce the existence of options/arguments.
Just as a note, I found that argparse is simpler and more useful than getopt, and it support required arguments.
http://docs.python.org/2/howto/argparse.html#id1
import argparse
parser = argparse.ArgumentParser()
parser.add_argument("echo", help="echo the string you use here")
args = parser.parse_args()
Command Line
$ python prog.py
usage: prog.py [-h] echo
prog.py: error: the following arguments are required: echo
In case this is useful to anyone. Here is a boiler plate that I use for creating a python script with command line options. It handles required options. If a required option is not specified, then the script will terminate with an error.
#!/usr/bin/python
import os
import sys
import getopt
import logging
# This will get the name of this file
script_name = os.path.basename(__file__)
default_loglevel = 'info'
##
# #brief Help document for this script. See the main function below.
#
help = f'''
{script_name} -c com_port [-o output_file] [--loglevel level]
Reads the temperature data from a radio. The temperature data is output in csv form.
examples:
Read table from radio attached to com4 and write the table to the file
output.csv.
{script_name} -c com4 -o output.csv
Read table from radio attached to com3 and write the table to stdout.
You can use IO redirection to send the contents where every you want.
# just print to the terminal
{script_name} -c com3
# redirect to another file
{script_name} -c com3 > somefile.csv
# filter out temperatures that are -100
{script_name} -c com3 | grep -v '^-100'
-c com_port
--com_port comport
Name of the COM port attached to the radio
-o output_file
--output output_file
If specified write the table data to the given file. If not specified
the data will be written to stdout.
--loglevel critical | error | warning | info | debug | notset
Control the verbosity of the script by setting the log level. Critical
is the least verbose and notset is the most verbose.
The default loglevel is {default_loglevel}.
These values correspond directly to the python logging module levels.
(i.e. https://docs.python.org/3/howto/logging.html#logging-levels)
-h
--help
print this message
'''
def print_help():
print(help, file=sys.stderr)
class RequiredOptions:
'''Just something to keep track of required options'''
def __init__(self, options=[]):
self.required_options = options
def add(self, option):
if option not in self.required_options:
self.required_options.append(option)
def resolve(self, option):
if option in self.required_options:
self.required_options.remove(option)
def optionsResolved(self):
if len(self.required_options):
return False
else:
return True
def main(argv):
# Use the logging module to print non table data. These prints will be sent
# to stderr. The verbosity of the script can by adjusted via the setLevel
# method.
#
logging.getLogger().setLevel(default_loglevel.upper())
try:
opts, args = getopt.getopt(argv,"hc:o:",["help", "com_port=", "output=","loglevel="])
except getopt.GetoptError as e:
print_help()
logging.exception(e)
sys.exit(2)
# This can be overridden with the --output option.
#
output_file = sys.stdout
# As the required options are encountered they are removed from this list.
# After all of the args have been processed, require_options should be
# empty.
#
required_options = RequiredOptions([ 'com_port' ])
for opt, arg in opts:
if opt in ('-h', '--help'):
print_help()
sys.exit(0)
elif opt in ("-o", "--output"):
output_file = open(arg, 'w')
elif opt in ("-c", "--com_port"):
com_port = arg
required_options.resolve('com_port')
elif opt in ("--loglevel"):
# Convert to uppercase
#
loglevel = arg.upper()
logging.getLogger().setLevel(loglevel)
else:
print_help()
# Verify that all of the required options have been specified
#
if not required_options.optionsResolved():
print_help()
logging.error("The following required options were not specified:" + ' '.join(required_options.required_options))
# indicate that there was an error by returning a non-zero value.
#
sys.exit(1)
# Now do your work
logging.debug('debug message')
logging.info('info message')
logging.warning('warn message')
logging.error('error message')
logging.critical('critical message')
if __name__ == "__main__":
main(sys.argv[1:])
I would just create global variable like argbit and use bitwise operation instead of flags for each arg. I used like:
argbit=1
for each arg loop:
case arg1: #mandatory
argbit <<= 1
do stuff and break
case arg2: #optional
do stuff and break
now based on your args it will be left shifted so at end just check its value
if argbit != value:
usage_and_exit()
if you have two mandatory args its value will be 4 like 2 ^ n.
Ran into the same problem, here's how I solved it
try:
required_argument1 # If argument is missing, it will error, we
# catch that error below in -except
required_argument2
required_argument3
except Error as e: # Whatever your error is (mine was a keyError)
print( 'argument ' + str(e) + is missing )

Categories

Resources