Running pylint programmatically with the function epylint.py_run - python

When trying to run epylint.py_run to lint a file I pass in the filename and command-line options as a string, as specified in the docs. The file gets analyzed but the command-line options I pass aren't being applied. How can I get the function to apply the options I'm passing?

There is a bug in epylint.Run which omit to give the options, hence your problem.
In your case you should rather use the lint(filename, options) function, where options should be passed as a list of strings).

There is a bug in epylint.Run. I've submitted an issue. This should work:
def Run():
if len(sys.argv) == 1:
print("Usage: %s [options] <filename or module>" % sys.argv[0])
sys.exit(1)
elif not osp.exists(sys.argv[-1]):
print("%s does not exist" % sys.argv[1])
sys.exit(1)
else:
sys.exit(lint(options=sys.argv[:-1], filename=sys.argv[-1]))

Related

How to check if the parameter exist in python

I would like to create a simple python script that will take a parameter from the console, and it will display this parameter. If there will be no parameter then I would like to display error message, but custom message not something like IndexError: list index out of range
Something like this:
if isset(sys.argv[1]):
print sys.argv[1];
else:
print "No parameter has been included"
if len(sys.argv) >= 2:
print(sys.argv[1])
else:
print("No parameter has been included")
For more complex command line interfaces there is the argparse module
in Python's standard library - but for simple projects taking just a couple parameters directly checking sys.argv is alright.
update as of 2019, the recomendation is to use the external library "click", as it provides very "Pythonic" ways of including complex documents in a way they are easily documented.
You can check the lenght
if len(sys.argv) > 1:
...
Or the try/except
try:
sys.argv[1]
except IndexError as ie:
print("Exception : {0}".format(ie))
import sys
try:
print sys.argv[1]
except IndexError:
print "No parameter has been included"
import sys
print sys.argv[0] # will print your file name
if len(sys.argv) > 1:
print sys.argv[1];
else:
print "No parameter has been included"
OR
import sys
try:
print sys.argv[1]
except IndexError, e:
print "No parameter has been included"
Just for fun, you can also use getopt which provides you a way of predefining the options that are acceptable using the unix getopt conventions.
import sys
import getopt
try:
opts, args = getopt.getopt(sys.argv[1:], "hvxrc:s:", ["help", "config=", "section="])
except getopt.GetoptError as err:
print ("Option error:", str(err))
opts=[]
for op , val in opts:
print ("option",op,"Argument",val)
if not opts:
print ("No parameter supplied")
In the above if an incorrect parameter is supplied all of the options are scrapped.
Examples of use would be:
python myprog.py -h
python myprog.py --help
python myprog.py -c123
python myprog.py --config=123
https://pymotw.com/2/getopt/
http://linux.about.com/library/cmd/blcmdl1_getopt.htm
without exception model using if else short hand, in single line we can read args
args = sys.argv
env = args[1:] and args[1] or None
username = args[2:] and args[2] or None
password = args[3:] and args[3] or None

Issue handling file from command line with biopython SeqIO

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.)

How to dynamically import variables after executing python script from within another script

I want to extract a variable named value that is set in a second, arbitrarily chosen, python script.
The process works when do it manually in pyhton's interactive mode, but when I run the main script from the command line, value is not imported.
The main script's input arguments are already successfully forwarded, but value seems to be in the local scope of the executed script.
I already tried to define value in the main script, and I also tried to set its accessibility to global.
This is the script I have so far
import sys
import getopt
def main(argv):
try:
(opts, args) = getopt.getopt(argv, "s:o:a:", ["script=", "operations=", "args="])
except getopt.GetoptError as e:
print(e)
sys.exit(2)
# script to be called
script = ""
# arguments that are expected by script
operations = []
argv = []
for (opt, arg) in opts:
if opt in ("-o", "--operations"):
operations = arg.split(',')
print("operations = '%s'" % str(operations))
elif opt in ("-s", "--script"):
script = arg;
print("script = '%s'" % script)
elif opt in ("-a", "--args"):
argv = arg.split(',')
print("arguments = '%s'" % str(argv))
# script should define variable 'value'
exec(open(script).read())
print("Executed '%s'. Value is printed below." % script)
print("Value = '%s'" % value)
if __name__ == "__main__":
main(sys.argv[1:])
The value variable has been put into your locals dictionary by the exec, but was not visible to the compiler. You can retrieve it like this:
print("Value = '%s'" % locals()['value'])
I would prefer an import solution
Using locals() as #cdarke suggested yielded the correct result!
exec(open(script).read())
print("Executed '%s'. Value is printed below." % script)
print("Value = '%s'" % locals()['value'])
In case your import needs to be dynamic, you can use
impmodule = __import__("modulename") # no .py suffix needed
then refer to value via
impmodule.value
There are several ways to achieve the same results.
See the answers on this topic on SO

Python optparse not seeing argument

I am trying to pass '-f nameoffile' to the program when I call it from the command line. I got this from the python sites documentation but when I pass '-f filename' or '--file=filename' it throws the error that I didnt pass enough arguments. If i pass -h the programs responds how it should and gives me the help. Any ideas? I imagine its something simple that I am overlooking. Any and all help is great, thanks, Justin.
[justin87#el-beasto-loco python]$ python openall.py -f chords.tar
Usage: openall.py [options] arg
openall.py: error: incorrect number of arguments
[justin87#el-beasto-loco python]$
#!/usr/bin/python
import tarfile
import os
import zipfile
from optparse import OptionParser
def check_tar(file):
if tarfile.is_tarfile(file):
return True
def open_tar(file):
try:
tar = tarfile.open(file)
tar.extractall()
tar.close()
except tarfile.ReadError:
print "File is somehow invalid or can not be handled by tarfile"
except tarfile.CompressionError:
print "Compression method is not supported or data cannot be decoded"
except tarfile.StreamError:
print "Is raised for the limitations that are typical for stream-like TarFile objects."
except tarfile.ExtractError:
print "Is raised for non-fatal errors when using TarFile.extract(), but only if TarFile.errorlevel== 2."
def check_zip(file):
if zipfile.is_zipfile(file):
return True
def open_zip(file):
try:
zip = zipfile.ZipFile(file)
zip.extractall()
zip.close()
#open the zip
print "GOT TO OPENING"
except zipfile.BadZipfile:
print "The error raised for bad ZIP files (old name: zipfile.error)."
except zipfile.LargeZipFile:
print "The error raised when a ZIP file would require ZIP64 functionality but that has not been enabled."
rules = ((check_tar, open_tar),
(check_zip, open_zip)
)
def checkall(file):
for checks, extracts in rules:
if checks(file):
return extracts(file)
def main():
usage = "usage: %prog [options] arg"
parser = OptionParser(usage)
parser.add_option("-f", "--file", dest="filename",
help="read data from FILENAME")
(options, args) = parser.parse_args()
if len(args) != 1:
parser.error("incorrect number of arguments")
file = options.filename
checkall(file)
if __name__ == '__main__':
main()
Your problem is probably the if len(args) != 1:. That is looking for an additional argument (i.e. not an option). If you remove that check and look at your options dictionary you should see {'filename': 'blah'}.
Your input filename isn't an option to the program, it's an argument:
def main():
usage = "Usage: %prog [options] FILE"
description = "Read data from FILE."
parser = OptionParser(usage, description=description)
(options, args) = parser.parse_args()
if len(args) != 1:
parser.error("incorrect number of arguments")
file = args[0]
checkall(file)
You can usually tell the difference because options generally have sensible defaults while arguments don't.
After parsing the options out of the argument list, you check that you were passed an argument. This is independent of the argument to -f. It sounds like you're just not passing this argument. Since you also don't actually use this argument, you should probably just remove the check on len(args).
You should set the 'action' attribute in the 'add_option()' method to 'store', this tells the optparse object to store the argument immediately following the option flag, though this is the default behavior. The value following the flag will then be stored in 'options.filename' and not in args. I also think that the
if len(args) != 1:
is also an issue, you will get the same message if len(args) is greater than or less than 1.

python and sys.argv

if len(sys.argv) < 2:
sys.stderr.write('Usage: sys.argv[0] ')
sys.exit(1)
if not os.path.exists(sys.argv[1]):
sys.stderr.write('ERROR: Database sys.argv[1] was not found!')
sys.exit(1)
This is a portion of code I'm working on. The first part I'm trying to say if the user doesn't type python programname something then it will exit.
The second part I'm trying to see if the database exists. On both places I'm unsure if I have the correct way to write out the sys.argv's by stderr or not.
BTW you can pass the error message directly to sys.exit:
if len(sys.argv) < 2:
sys.exit('Usage: %s database-name' % sys.argv[0])
if not os.path.exists(sys.argv[1]):
sys.exit('ERROR: Database %s was not found!' % sys.argv[1])
In Python, you can't just embed arbitrary Python expressions into literal strings and have it substitute the value of the string. You need to either:
sys.stderr.write("Usage: " + sys.argv[0])
or
sys.stderr.write("Usage: %s" % sys.argv[0])
Also, you may want to consider using the following syntax of print (for Python earlier than 3.x):
print >>sys.stderr, "Usage:", sys.argv[0]
Using print arguably makes the code easier to read. Python automatically adds a space between arguments to the print statement, so there will be one space after the colon in the above example.
In Python 3.x, you would use the print function:
print("Usage:", sys.argv[0], file=sys.stderr)
Finally, in Python 2.6 and later you can use .format:
print >>sys.stderr, "Usage: {0}".format(sys.argv[0])
I would do it this way:
import sys
def main(argv):
if len(argv) < 2:
sys.stderr.write("Usage: %s <database>" % (argv[0],))
return 1
if not os.path.exists(argv[1]):
sys.stderr.write("ERROR: Database %r was not found!" % (argv[1],))
return 1
if __name__ == "__main__":
sys.exit(main(sys.argv))
This allows main() to be imported into other modules if desired, and simplifies debugging because you can choose what argv should be.

Categories