using argparse in a python script - python

I have some input file in a directory and want to make a python script with 2 functions and run the script for all of the input files in the same directory.
the script that I made still does not work. there are 2 functions. the first one is the one which takes the input files and returns the output files. if I run this function on every single input file, it will work perfectly. so there is no problem with the function "convert".
the 2nd function in main function which is made for "argparse". the script has problem in this function.
import argparse
import pytools
def convert(infile, outfile):
x = pytools.split(infile)
x.coverage(bh=True, split=True)\
.saveas(outfile, type='bh')
print "done"
return
def main():
parser=argparse.ArgumentParser()
parser.add_argument("-b", "--infile", required=True)
parser.add_argument("-o", "--output", required=True)
args = parser.parse_args()
input = args.infile
output = convert(args.infile)
if __name__ == '__main__':
main()
my problem is that, I do not know if introducing the input files and call for output files is done in a correct way or not. in fact I think the problem of this script is in this part:
input = args.infile
output = convert(args.infile)
do you know how to fix the script?
this is the problem I get after running the script:
Traceback (most recent call last):
File "bam2bg.py", line 39, in <module>
main()
File "bam2bg.py", line 35, in main
input = args.infile
AttributeError: 'Namespace' object has no attribute 'infile'

Related

How to implement clear in cmd.Cmd?

I am working on a custom command line interpreter, and I want to implement the 'clear' command, just like the the one in bash shell. Is there any way to do that?
I have attempted it but I don't think it is correct at all:
#!/usr/bin/python3
import cmd
import sys
import os
class HBNBCommand(cmd.Cmd):
"""Command line interpreter"""
def do_clear(self):
"""Clear command similar to clear from shell"""
os.system('clear')
if __name__ == '__main__':
HBNBCommand().cmdloop()
When I try it, it gives me the exception:
Traceback (most recent call last):
File "/home/leuel/PycharmProjects/AirBnB_clone/./console.py", line 22, in <module>
HBNBCommand().cmdloop()
File "/usr/lib/python3.10/cmd.py", line 138, in cmdloop
stop = self.onecmd(line)
File "/usr/lib/python3.10/cmd.py", line 217, in onecmd
return func(arg)
TypeError: HBNBCommand.do_clear() takes 1 positional argument but 2 were given
When inheriting from cmd to build your custom shell, methods expect at least one argument. To quote from this resource, "The interpreter uses a loop to read all lines from its input, parse them, and then dispatch the command to an appropriate command handler. Input lines are parsed into two parts. The command, and any other text on the line."
Since do_clear has not provided for an argument, the command cannot handle any additional input, even when that input does not exist.
class HBNBCommand(cmd.Cmd):
"""Command line interpreter"""
def do_clear(self, arg):
"""Clear command similar to clear from shell"""
os.system('clear')
if __name__ == '__main__':
HBNBCommand().cmdloop()
You can also refer to the Cmd example in the Python docs: https://docs.python.org/3/library/cmd.html#cmd-example

Index error while working with sys argv in PyCharm

I'm using 'sys' module to get the filename as an argument in the command line while I'm running the script in cmd it is working as I want, but if I run this in PyCharm it raises an error Index Error: list index out of range. How to get rid of this error in PyCharm?
Here is the Code I'm trying to run:
import sys
def read_lines(file):
list_of_numbers = []
with open(file, mode='r') as read_file:
for number in read_file:
number = number.strip()
list_of_numbers.append(number)
return list_of_numbers
if __name__ == '__main__':
fun = read_lines(sys.argv[1])
print(fun)
While running the script directly from pycharm it raises following error:
Traceback (most recent call last):
File "D:\pythonProjects\test.py", line 10, in <module>
fun = read_lines(sys.argv[1])
IndexError: list index out of range
Presumably that's because you don't provide any arguments when running the script in PyCharm.
You can run the following script to print all the arguments:
import sys
if __name__ == '__main__':
print(sys.argv)
If you run it in the command line something like this
python3 test.py filename.txt
You should the output
['test.py', 'filename.txt']
(the first argument is the name of your script).
In PyCharm, you also have to specify filename.txt as a parameter.
Otherwise, you only get
['test.py']
which means that there is no element 1, hence the IndexError.
You can fix it by adding the filename.txt parameter to your run configuration in PyCharm.

Is there a generic way to execute different python files, depending on sys.args?

I would like to create a python file that can be run from the terminal - this file will be in charge of running various other python files depending on the functionality required along with their required arguments, respectively. For example, this is the main file:
import sys
from midi_to_audio import arguments, run
files = ["midi_to_audio.py"]
def main(file, args):
if file == "midi_to_audio.py":
if len(args) != arguments:
print("Incorrect argument length")
else:
run("test","t")
if __name__ == '__main__':
sys.argv.pop(0)
file = sys.argv[0]
sys.argv.pop(0)
if file not in files:
print("File does not exist")
else:
main(file, sys.argv)
And this is the first file used in the example (midi_to_audio.py):
arguments = 2
def run(file, output_file):
print("Ran this method")
So depending on which file I've specified when running the cmd via the terminal, it will go into a different file and call its run method. If the arguments are not as required in each file, it will not run
For example: >python main.py midi_to_audio.py file_name_here output_name_here
My problem is that, as I add more files with their own "arguments" and "run" functions, I wonder if python is going to get confused with which arguments or which run function to execute. Is there a more safer/generic way of doing this?
Also, is there a way of getting the names of the python files depending on which files I've imported? Because for now I have to import the file and manually add their file name to the files list in main.py
Your runner could look like this, to load a module by name and check it has run, and check the arguments given on the command line, and finally dispatch to the module's run function.
import sys
import importlib
def main():
args = sys.argv[1:]
if len(args) < 1:
raise Exception("No module name given")
module_name = args.pop(0).removesuffix(".py") # grab the first argument and remove the .py suffix
module = importlib.import_module(module_name) # import a module by name
if not hasattr(module, 'run'): # check if the module has a run function
raise Exception(f"Module {module_name} does not have a run function")
arg_count = getattr(module, 'arguments', 0) # get the number of arguments the module needs
if len(args) != arg_count:
raise Exception(f"Module {module_name} requires {arg_count} arguments, got {len(args)}")
module.run(*args)
if __name__ == '__main__':
main()
This works with the midi_to_audio.py module in your post.

P4Python run method does not work on empty folder

I want to search a Perforce depot for files.
I do this from a python script and use the p4python library command:
list = p4.run("files", "//mypath/myfolder/*")
This works fine as long as myfolder contains some files. I get a python list as a return value. But when there is no file in myfolder the program stops running and no error message is displayed. My goal is to get an empty python list, so that I can see that this folder doesn't contain any files.
Does anybody has some ideas? I could not find information in the p4 files documentation and on StackOverflow.
I'm going to guess you've got an exception handler around that command execution that's eating the exception and exiting. I wrote a very simple test script and got this:
C:\Perforce\test>C:\users\samwise\AppData\local\programs\python\Python36-32\python files.py
Traceback (most recent call last):
File "files.py", line 6, in <module>
print(p4.run("files", "//depot/no such path/*"))
File "C:\users\samwise\AppData\local\programs\python\Python36-32\lib\site-packages\P4.py", line 611, in run
raise e
File "C:\users\samwise\AppData\local\programs\python\Python36-32\lib\site-packages\P4.py", line 605, in run
result = P4API.P4Adapter.run(self, *flatArgs)
P4.P4Exception: [P4#run] Errors during command execution( "p4 files //depot/no such path/*" )
[Error]: "//depot/no such path/* - must refer to client 'Samwise-dvcs-1509687817'."
Try something like this ?
import os
if len(os.listdir('//mypath/myfolder/') ) == 0: # Do not execute p4.run if directory is empty
list = []
else:
list = p4.run("files", "//mypath/myfolder/*")

Python 3: How to call function from another file and pass arguments to that function ?

I want to call a function from another file and pass arguments from current file to that file. With below example, In file bye.py I want to call function "me" from "hi.py" file and pass "goodbye" string to function "me". How to do that ? Thank you :)
I have file hi.py
def me(string):
print(string)
me('hello')
bye.py
from hi import me
me('goodbye')
What I got:
hello
goodbye
What I would like:
goodbye
Generally when you create files to be imported you must use if __name__ == '__main__' which evaluates to false in case you are importing the file from another file. So your hi.py may look as:
def me(string):
print(string)
if __name__ == '__main__':
# Do some local work which should not be reflected while importing this file to another module.
me('hello')

Categories

Resources