I have the following snippet where i am checking for first argument and runninginto following error..can anyone help on how to make the first argument optional?
SNIPPET CODE:-
branch = ''
if sys.argv[1]:
branch = sys.argv[1]
ERROR:-
Traceback (most recent call last):
File "test.py", line 102, in <module>
main()
File "test.py", line 66, in main
if sys.argv[1]:
IndexError: list index out of range
For inputting parameters into python you can use the getopt module. Here parameters can be optional and can be inputted in any order as long at the correct flag is present.
In the example below the user has two optional parameters to set, the input-file name and the database name. The code can be called using
python example.py -f test.txt -d HelloWorld
or
python example.py file=test.txt database=HelloWorld
or a mix and match of both.
The flags and names can be changed to reflect your needs.
import getopt
def main(argv):
inputFileName = ''
databaseName = ''
try:
opts, args = getopt.getopt(argv,"f:d:",["file=","database="])
except getopt.GetoptError:
print('-f <inputfile> -d <databasename> -c <collectionname>')
sys.exit()
for opt, arg in opts:
if opt in ('-f','--file'):
inputFileName = arg
elif opt in ('-d','--database'):
databaseName = arg
if __name__ == "__main__":
main(sys.argv[1:])
Use exception handling(EAFP):
try:
branch = sys.argv[1]
except IndexError:
branch = ''
You can use:
branch = sys.argv[1] if len(sys.argv) >= 2 else ''
Related
I am running a python file at command prompt and it is working fine. Execution of the file as
python myfile.py -d device01 -s on and this is working. when I import the same class from another file, it's not working.
Source code:
#!/usr/bin/env python3
import pytuya
import sys
import getopt
import json
def smartlite(argv):
device = ''
state = ''
try:
opts, args = getopt.getopt(argv,"hd:s:",["help", "device=", "state="])
except getopt.GetoptError:
print (sys.argv[0], '-d <device> -s <state>')
sys.exit(2)
for opt, arg in opts:
if opt in ("-h", "--help"):
print (sys.argv[0], '-d <device> -s <state>')
sys.exit()
elif opt in ("-d", "--device"):
device = arg
elif opt in ("-s", "--state"):
state = arg
filename = "p.json"
if filename:
with open(filename, 'r') as f:
datafile = json.load(f)
print ('Device is', device)
print ('State is', state)
print (datafile["devices"][device]["uuid"])
print (datafile["devices"][device]["key"])
print (datafile["devices"][device]["ip"])
d = pytuya.OutletDevice(datafile["devices"][device]["uuid"], datafile["devices"][device]["ip"], datafile["devices"][device]["key"])
data = d.status() # NOTE this does NOT require a valid key
print('Dictionary %r' % data)
print('state (bool, true is ON) %r' % data['dps']['1']) # Show status of first controlled switch on device
# Toggle switch state
switch_state = data['dps']['1']
data = d.set_status(not switch_state) # This requires a valid key
if data:
print('set_status() result %r' % data)
sys.exit(0)
if __name__ == "__main__":
smartlite(sys.argv[1:])
The above code is working when I run at command prompt as
\.> python myfile.py -d device01 -s on
when I am calling the above code from another file I am getting an error.
Importing the library of smartlite.
from sourcefolder.pytuya import smartlite # this is good.
try:
smartlite.get("-d Lite01 -s on")
#os.system('python pytuya/mypytuya.py -d Lite01 -s on')
except sr.UnknownValueError:
print('error')
except sr.RequestError as e:
print('faile'.format(e))
error when executing.
('Device is', '')
('State is', '')
Traceback (most recent call last):
File "voicetotext.py", line 22, in <module>
smartlite("-d Lite01 -s on")
File "/home/respeaker/voice-engine/examples/pytuya/mypytuya.py", line 34, in smartlite
print (datafile["devices"][device]["uuid"])
KeyError: ''
Thank you guys this conversation helped me.
I am able to send the arguments now to the fuction in this format and it got worked.
if a=b:
smartlite(['-d','device01','-s','on'])
You have several options:
(a) Edit your .bashrc, add something like:
export PYTHONPATH="$HOME/dir-base-sourcefolder"
(b) Review the directory structure. Check the relative depth from the module and the caller. Try with:
from .sourcefolder.pytuya import smartlite
from ..sourcefolder.pytuya import smartlite
This is my first attempt at using commandline args other than the quick and dirty sys.argv[] and writing a more 'proper' python script. For some reason that I can now not figure out, it seems to be objecting to how I'm trying to use the input file from the command line.
The script is meant to take an input file, some numerical indices, and then slice out a subset region of the file, however I keep getting errors that the variable I've given to the file I'm passing in is not defined:
joehealey#7c-d1-c3-89-86-2c:~/Documents/Warwick/PhD/Scripts$ python slice_genbank.py --input PAU_06042014.gbk -o test.gbk -s 3907329 -e 3934427
Traceback (most recent call last):
File "slice_genbank.py", line 70, in <module>
sub_record = record[start:end]
NameError: name 'record' is not defined
Here's the code, where am I going wrong? (I'm sure its simple):
#!/usr/bin/python
# This script is designed to take a genbank file and 'slice out'/'subset'
# regions (genes/operons etc.) and produce a separate file.
# Based upon the tutorial at http://biopython.org/DIST/docs/tutorial/Tutorial.html#htoc44
# Set up and handle arguments:
from Bio import SeqIO
import getopt
def main(argv):
record = ''
start = ''
end = ''
try:
opts, args = getopt.getopt(argv, 'hi:o:s:e:', [
'help',
'input=',
'outfile=',
'start=',
'end='
]
)
if not opts:
print "No options supplied. Aborting."
usage()
sys.exit(2)
except getopt.GetoptError:
print "Some issue with commandline args.\n"
usage()
sys.exit(2)
for opt, arg in opts:
if opt in ("-h", "--help"):
usage()
sys.exit(2)
elif opt in ("-i", "--input"):
filename = arg
record = SeqIO.read(arg, "genbank")
elif opt in ("-o", "--outfile"):
outfile = arg
elif opt in ("-s", "--start"):
start = arg
elif opt in ("-e", "--end"):
end = arg
print("Slicing " + filename + " from " + str(start) + " to " + str(end))
def usage():
print(
"""
This script 'slices' entries such as genes or operons out of a genbank,
subsetting them as their own file.
Usage:
python slice_genbank.py -h|--help -i|--input <genbank> -o|--output <genbank> -s|--start <int> -e|--end <int>"
Options:
-h|--help Displays this usage message. No options will also do this.
-i|--input The genbank file you which to subset a record from.
-o|--outfile The file name you wish to give to the new sliced genbank.
-s|--start An integer base index to slice the record from.
-e|--end An integer base index to slice the record to.
"""
)
#Do the slicing
sub_record = record[start:end]
SeqIO.write(sub_record, outfile, "genbank")
if __name__ == "__main__":
main(sys.argv[1:])
It's also possible there's an issue with the SeqIO.write syntax, but I haven't got as far as that yet.
EDIT:
Also forgot to mention that when I use `record = SeqIO.read("file.gbk", "genbank") and write the file name directly in to the script, it works correctly.
As said in the comments, your variable records is only defined in the method main() (the same is true for start and end), thus it is not visible for the rest of the program.
You can either return the values like this:
def main(argv):
...
...
return record, start, end
Your call to main() can then look like this:
record, start, end = main(sys.argv[1:])
Alternatively, you can move your main functionality into the main function (as you did).
(Another way is to define the variables in the main program and the use the global keyword in your function, this is, however, not recommended.)
I modified the sample code given here:
sample code for getopt
as follows, but it does not work. I am not sure what I am missing. I added a "-j" option to this existing code. Eventually, I want to add as many as required command option to meet my needs.
When I give input as below, it does not print anything.
./pyopts.py -i dfdf -j qwqwqw -o ddfdf
Input file is "
J file is "
Output file is "
Can you please let me know whats wrong here?
#!/usr/bin/python
import sys, getopt
def usage():
print 'test.py -i <inputfile> -j <jfile> -o <outputfile>'
def main(argv):
inputfile = ''
jfile = ''
outputfile = ''
try:
opts, args = getopt.getopt(argv,"hij:o:",["ifile=","jfile=","ofile="])
except getopt.GetoptError:
usage()
sys.exit(2)
for opt, arg in opts:
if opt == '-h':
usage()
sys.exit()
elif opt in ("-i", "--ifile"):
inputfile = arg
elif opt in ("-j", "--jfile"):
jfile = arg
elif opt in ("-o", "--ofile"):
outputfile = arg
print 'Input file is "', inputfile
print 'J file is "', jfile
print 'Output file is "', outputfile
if __name__ == "__main__":
main(sys.argv[1:])
Your error is omitting a colon following the i option. As stated by the link you supplied:
options that require an argument should be followed by a colon (:).
Therefore, the corrected version of your program should contain the following:
try:
opts, args = getopt.getopt(argv,"hi:j:o:",["ifile=","jfile=","ofile="])
except getopt.GetoptError:
usage()
sys.exit(2)
Executing it with the specified arguments derives the expected output:
~/tmp/so$ ./pyopts.py -i dfdf -j qwqwqw -o ddfdf
Input file is " dfdf
J file is " qwqwqw
Output file is " ddfdf
However, as a comment to your question specifies, you should use argparse rather than getopt:
Note: The getopt module is a parser for command line options whose API is designed to be familiar to users of the C getopt() function. Users who are unfamiliar with the C getopt() function or who would like to write less code and get better help and error messages should consider using the argparse module instead.
I'm learning Python and started putting together the below code. I'm trying to get the fread function working correctly but I'm getting an error.
I've tried a few ways to fix it but of course if I don't know what's causing it I'm never going to fix it.
I'm hoping someone could help me out.
Error
unknown#ubuntu:~$ ./attack.py -f wordfile.txt
Traceback (most recent call last):
File "./attack.py", line 63, in <module>
print fread(list)
File "./attack.py", line 20, in fread
flist = open(list).readlines()
TypeError: coercing to Unicode: need string or buffer, type found`
CODE
#!/usr/bin/python
import sys, getopt, socket, fileinput, traceback
import dns.query, dns.message, dns.name, adns
from Queue import Queue
from threading import Thread
def usage():
print "-h --help: help\n"
print "-f --file: File to read bruteforce domain list from.\n"
print "-p --proxy: Proxy address and port. e.g http://192.168.1.64:8080\n"
print "-d --domain: Domain to bruteforce.\n"
print "-t --thread: Thread count.\n"
print "-e: Turn debug on.\n"
sys.exit()
def fread(list, *args):
flist = open(list).readlines()
return flist
def addcheck(fcontent):
data =[]
c=adns.init()
for sub in file:
SubDomain = fcontent + domain
data[SubDomain] = c.synchronous(SubDomain, adns.rr.A)
return data
def main(argv):
list = None
proxy = None
domain = None
FILE= None
try:
opts, argv =getopt.getopt(argv, "h:f:p:d:t:e",["help", "file=", "proxy=", "domain=", "thread="])
except getopt.GetoptError as err:
print str(err)
usage()
sys.exit(2)
for opt, arg in opts:
if opt in ("-h", "--help"):
usage()
sys.exit()
elif opt in ("-f", "--file"):
list = arg
elif opt in ("-p", "--proxy"):
proxy = arg
elif opt in ("-d", "--domain"):
domain = arg
elif opt in ("-t", "--thread"):
thread = arg
elif opt in '-e':
global _debug
print fread(list)
if __name__ == "__main__":
main(sys.argv[1:])
You are passing in the list type object here:
print fread(list)
This is outside of the main function, so list is still bound to the built-in type.
You probably meant that line to be part of the main() function. If so, indent it further to match the rest of the code in the function.
You really should not use list as a variable name, however. There already is a built-in type of that name; as a result your indentation error gave you a confusing exception message. Perhaps fname or filename would have been a better choice.
Thank you for quack in pointing out the off-by-one!
The following code is my first attempt in writing code with Optparse.
How can you fix the following bug in getting the help by Optparse?
#!/usr/bin/env python
import sys
import os
from optparse import OptionParser
e = sys.argv[1]
b = sys.argv[2]
no = sys.argv[3]
def set_figu(figu):
sum = 777
return sum
def main():
usage = "Usage: negative_bin_base.py <eksponentti> <siirre> <figu>"
parser = OptionParser(usage)
parser.add_option("-h", "--help", dest="help",
help="get synopsis of parameters")
# print the output of the work-horse
print set_figu(no)
(options, args) = parser.parse_args()
if len(args) < 4:
parser.error("incorrect number of arguments")
if options.informative:
print "reading %s..." % options.help
if __name__ == "__main__":
main()
Example of wrong output with correct number of parameters
python negative_bin_base.py 13 13 332
Traceback (most recent call last):
File "negative_bin_base.py", line 37, in <module>
main()
File "negative_bin_base.py", line 26, in main
help="get synopsis of parameters")
File "/usr/lib/python2.6/optparse.py", line 1020, in add_option
self._check_conflict(option)
File "/usr/lib/python2.6/optparse.py", line 995, in _check_conflict
option)
optparse.OptionConflictError: option -h/--help: conflicting option string(s): -h, --help
Constructor for class optparse.OptionParser(...) has optional named parameter 'add_help_option', which defaults to 'True'. You will have to explicitly reject default help option and message, if you want to provide your own.
parser = OptionParser(usage, add_help_option=False)
The bug is that your arguments array includes the name of the script as sys.argv[0]. Thus your if is off-by-one:
# python sys.argv[0] sys.argv[1] sys.argv[2] sys.argv[3]
if len(sys.argv) < 4:
sys.exit(usage)
This should do what you require, based on your example above:
#!/usr/bin/env python
from optparse import OptionParser
def main():
usage = "Usage: negative_bin_base.py <eksponentti> <siirre> <figu>"
parser = OptionParser(usage)
(options, args) = parser.parse_args()
if len(args) != 3:
parser.error("incorrect number of arguments")
e = args[0]
b = args[1]
no = args[2]
# ...
if __name__ == "__main__":
main()
For using optparse here's what I normally do:
separate command line parsing from your main code base for better modularization.
(Put the processing right after "if __name__ == "__main__"")
Let optparse handle your help.
(Use parser.print_help())
Use the optparse constructs, if you don't like them just parse sys.argv yourself.
(use add_option to define your necessary options)
Here's how I would write your sample using the optparse library:
def main():
print 'Welcome to the main event!'
if __name__ == '__main__':
import optparse
parser = optparse.OptionParser()
parser.add_option("-e", "--eksponentti", dest="eksponentti",
help="This is help for <eksponentti>.",
default=None)
parser.add_option("-s", "--siirre", dest="siirre",
help="This is help for <siirre>.",
default=None)
parser.add_option("-f", "--figu", dest="figu",
help="This is help for <figu>.",
default=None)
(options, args) = parser.parse_args()
if options.eksponentti and options.siirre and options.figu:
main()
else:
print "ERROR -- Expected Arguments not given!"
parser.print_help()
Running this without the necessary options will give the following output:
(It's a little prettier than I can format it here...)
ERROR -- Expected Arguments not given! Usage: parm.py [options]
Options:
-h, --help show this help message and exit
-e EKSPONENTTI, --eksponentti=EKSPONENTTI This is help for <eksponentti>.
-s SIIRRE, --siirre=SIIRRE This is help for <siirre>.
-f FIGU, --figu=FIGU This is help for <figu>.