I'm trying to make a custom command line to control a robotic arm.
So I want to be able to run the program and type in servoMove(arg1,arg2) and have arg1 and arg2 get transferred into the function servoMove.
servoPos = [0,1,2,3,4]
def servoMove(servo,angle):
servoPos[servo] = angle
print(servoPos[servo])
def commands(cmd):
if cmd == 'servoMove('+arg1+','+arg2+')':
servoMove(arg1,arg2)
else:
print("[Error] - Unknown Command")
commands(input(""))
Clearly, the code below doesn't work for this.
if cmd == 'servoMove('+arg1+','+arg2+')':
servoMove(arg1,arg2)
Does anybody know how I can do this?
You can use a regular expression to parse the command.
import re
def commands(cmd):
m = re.match(r'servoMove\((\d+),(\d+)\)', cmd)
if m:
servoMove(int(m.group(1)), int(m.group(2)))
return
# Put similar tests for other commands here
# ...
print("[Error] - Unknown Command")
This is a really crude way to do it -- if the user doesn't enter the command exactly right it will complain that the command is unknown. If you want something more robust, you need to learn how to write a real parser. Or use a better user interface, such as Tkinter to implement a form that the user can fill out.
You can use the cmd module to build a command line interface.
Here's an example:
import cmd
servoPos = [0,1,2,3,4]
def servoMove(servo,angle):
servoPos[servo] = angle
print(servoPos[servo])
class ServoShell(cmd.Cmd):
prompt = '=> '
def do_servoMove(self, arg):
'Edit this to give a description to the function when typing ?'
servoMove(*parse(arg))
def parse(arg):
'Convert a comma separated string into a tuple'
return tuple(map(int, arg.strip('()').split(',')))
if __name__ == '__main__':
ServoShell().cmdloop()
Just looking at the structure the problem is in the if statement: arg1 and arg2 are undefined at that stage, so you'll get a False. For starters you'd want to replace that with something like:
#Look at the nine first characters to see if they match your function
if cmd[:9] == 'servoMove':
To extract your arguments, I'd use some string manipulation as in here. I've sliced the input to take the text between "(" and "," as arg1, and "," and ")" as arg2.
arg1 = cmd[cmd.find("(")+1:cmd.find(",")]
arg2 = cmd[cmd.find(",")+1:cmd.find(")")]
Putting it together:
def commands(cmd):
if cmd[:9] == 'servoMove':
arg1 = cmd[cmd.find("(")+1:cmd.find(",")]
arg2 = cmd[cmd.find(",")+1:cmd.find(")")]
servoMove(arg1, arg2)
else:
print("[Error] - Unknown Command")
Related
Recently i saw a post about someone making a program that could control a computer it was launched on. (it was this one) Add commands to user input
I was really interested in it and I wanted to replicate it and improve my python skills on the way.
After watching some tutorials I had the ability to send and recieve emails and started working on some commands. First I added the ability to take screenshots as its the most important one. I then added functions and commands to do other stuff. Then I wanted to add a help command to display all commands if there is no args and the description of a specific command if there is an args. I first added the one without args and this is the code for it:
import json
user_input = "$say hello\n$help"
def help(*args):
if args == ():
for func_name, aliases in info_json.items():
print(func_name)
else:
pass
#print the description for the command
def command1():
print("I am command 1.")
def command2():
print("I am command 2.")
def command3():
print("I am command 3.")
def say(*args):
print(f"You said i should say \"{' '.join(args)}\"! Very cool :D")
def pause(sec):
print(f"I waited for {sec} seconds!")
commands = {
"$help":help,
"$pause":pause,
"$say":say,
"$command1":command1,
"$command2":command2,
"$command3":command3,
}
with open("commands.json") as json_file:
help_json = json.load(json_file)
def call_command(BEFEHL):
function, *args = BEFEHL.split(' ')
commands[function](*args)
for line in user_input.split("\n"):
try:
call_command(line)
except KeyError:
print("This command does not exist.")
I replaced the actual functions with print statements like the original author did :D
This code worked very well and I started to work on the description on specific functions. I created the commands.json example:
{
"command1": ["This command is command 1. It prints out 'I am command 1' "],
"command2": ["This command is command 2. It prints out 'I am command 2' "],
"command3": ["This command is command 3. It prints out 'I am command 3' "]
}
Is there any way you can print out the stuff in the json which stands behind the command? An example use would be:
>>> $help command1
print("This is command 1. It prints out 'I am command 1' ")
I would really appreciate to know if this is possible! :D
When you load a json, it basically acts like a Python dictionary, so you can retrieve the description of the command from its key, which you are passing as parameter.
Your help() function should look something like this:
def help(*args):
if args == ():
for func_name, aliases in help_json.items():
print(func_name)
else:
print(help_json.get(args[0], "Command does not exist"))
The second argument "Command does not exist" is the default value to print when the get() cannot find the key in the dictionary.
I have a main python3 file as follows:
import additionalfunctions
userIn = input("Select Function and command line arguments: ")
'additionalfunctions.py' is as follows:
def arbitraryfunction(arg):
print("you entered the value: " + str(arg))
The issue I am facing is that I need to select this function with with the 'input()' in the main python file, as well as pass the one argument to it. Does anyone know how to parse the variable 'userIn' in order to select and run a function, and pass arguments to it?
Any help you can give would be much appreciated!
You can use the default package argparse
And create a function like below.
Code:
import argparse
#>>>>>>>>>>>>>>>>>>>>>>> ARGUMENT PARSING <<<<<<<<<<<<<<<<<<<<<<<<<<<<
def args():
parser = argparse.ArgumentParser()
parser.add_argument('-A','--Arg1',type=int,help='I am Argument 1',required=False)
parser.add_argument('-B','--Arg2',type=str,help='I am Argument 2',required=True)
parser.add_argument('-C','--Arg3',type=str,help='I am Argument 3',required=True)
args = parser.parse_args()
print("PARSING ARGUMENTS COMPLETED")
argparse documentation : https://docs.python.org/3/library/argparse.html
In addition to High-Octane answer, which is totally right, once you have the command line parameters, you can use exec() to run the selected function and pass the arguments to it. Try this based on your own code:
def arbitraryfunction(arg):
print("you entered the value: " + str(arg))
allowed_functions = ['arbitraryfunction']
# write "arbitraryfunction 0" or similar when asked
userIn = input("Select Function and command line arguments: ")
args = userIn.split(" ")
if len(args) >= 2:
fun = args[0]
arg = args[1]
if fun in allowed_functions:
exec(fun + "(" + str(arg) + ")")
else:
print("Function not found. Please try again")
Then,you have to import additionalfunctions (I included it into the same script for simplicity) like this:
from additionalfunctions import *
Disclaimer: This should not be used in any production sensitive environment as it can execute malicious scripts.
I'm making my own python CLI and i want to pass only String arguments
import sys
import urllib, json
# from .classmodule import MyClass
# from .funcmodule import my_function
def main():
args = sys.argv[1:]
#print('count of args :: {}'.format(len(args)))
#for arg in args:
# print('passed argument :: {}'.format(arg))
#always returns true even if i don't pass the argument as a "String"
if(isinstance(args[0], str)):
print('JSON Body:')
url = args[0]
response = urllib.urlopen(url)
data = json.loads(response.read())
print(data)
# my_function('hello world')
# my_object = MyClass('Thomas')
# my_object.say_name()
if __name__ == '__main__':
main()
I execute it by api "url" and this is the correct output:
Although when i'm trying to execute api url without passing it as a String my output is a little odd:
How can i accept only String arguments?
What I've tried so far:
Found this solution here but it didn't work for me (couldn't recognize the join() function)
problem isn't a python issue. It's just that your URL contains a &, and on a linux/unix shell, this asks to run your command in the background (and the data after & is dropped). That explains the [1]+ done output, with your truncated command line.
So you have to quote your argument to avoid it to be interpreted (or use \&). There's no way around this from a Un*x shell (that would work unquoted from a Windows shell for instance)
import pywaves as pw
import sys, getopt
amount = 0
receive = ''
try:
options, remainder = getopt.getopt(
sys.argv[1:],
'r:a',
['receive',
'amount',
])
except getopt.GetoptError as err:
print('ERROR:', err)
sys.exit(1)
for opt, arg in options:
if opt in ('-a', '--amount'):
amount = arg
elif opt in ('-r', '--receive'):
receive = arg
print('OPTIONS :', options)
myAddress = pw.Address(privateKey='MYPRIVATEKEY')
otherAddress = pw.Address(receive)
myToken = pw.Asset('MYADDRESS')
myAmount = amount
myAddress.sendAsset(otherAddress, myToken, myAmount)
I tried run the code above and it seems my option "a" was not captured. What should I do to get it working?
I run the following command line
python this.py -r 3PFPovgPu3aBWA1krU544tPDTFiHgpvu7q1 -a 150
It returns
('OPTIONS :', [('-r', '3PFPovgPu3aBWA1krU544tPDTFiHgpvu7q1'), ('-a', '')])
I not sure why the "a" value was empty. How do I change my code to make it work properly?
You need to add a colon after the second parameter 'a'. So try
getopt.getopt(sys.argv[1:],'r:a:',['receive','amount'])
See the documentation for getopt, there it is said clearly:
Parses command line options and parameter list. args is the argument list to be parsed, without the leading reference to the running program. Typically, this means sys.argv[1:]. options is the string of option letters that the script wants to recognize, with options that require an argument followed by a colon (':'; i.e., the same format that Unix getopt() uses).
I am trying to write an interactive shell in python for administering different type of hardware for configuring and issuing some set of commands.
How it will work:
So, once I got into the interactive shell prompt, I need to type a hardware name say HardwareA, after that my shell prompt will change to HardwareA. Once i got a specific Hardware prompt, after that what ever cmd(s) or option(s) I type will parse and called a particular function or methods from HardwareA module.
To make this working, I was trying to get some idea using argparse or optparse along with cmd module.
But so far I am not able to get a clear picture or any good docs to start with.
So, if anybody had some kind of solution or good link, please let me know and throw me some light.
Here is my snippet:
import cmd, shlex
import argparse
class ChooseHardware(cmd.Cmd):
"""Simple command processor example."""
hardware = [ 'netapp', 'isilon', 'ibm' ]
def do_netapp(self, argv):
parser = argparse.ArgumentParser(description='Process netapp argument.')
parser.add_argument('--qtree', dest='qtree',
help='qtree name')
args = parser.parse_args(argv.split())
print args
def do_isilon(self, argv):
pass
def do_ibm(self, argv):
pass
def do_EOF(self, line):
return True
def do_exit(self, s):
return True
def do_help(self, h):
print 'Unknown: hardware type'
def help_exit(self):
print "Exit the interpreter."
print "You can also use the Ctrl-D shortcut."
if __name__ == '__main__':
obj = ChooseHardware()
obj.prompt = 'cmd_prompt:'
obj.cmdloop()
Output:
yopy:/test$ python choose_hw.py
cmd_prompt:
cmd_prompt:netapp
Namespace(qtree=None)
cmd_prompt:netapp --qtree /opt/var
Namespace(qtree='/opt/var')
cmd_prompt: