I'm trying to implement a small script to manage a localhost with an FTP connection in Python from the command line and using the appropriate "ftplib" module. I would like to create a sort of raw input for the user but with some commands already setup.
I try to explain better:
Once I have created the FTP connection and login connection been successfully completed through username and password, i would show a sort of "bash shell" with the possibility to use the most famous UNIX commands ( for example cd and ls respectively to move in a directory and show file/folders in the current path ).
For example i could do this:
> cd "path inside localhost"
thus showing directories or:
> ls
to show all files and directories in that particular path. I've no idea how to implement this so i ask you some advices.
I thank you so much in advance for the help.
It sounds like the command line interface is that part that you are asking about. One good way to map user inputs to commands is to use a dictionary and the fact that in python you can run a reference to a function by putting () after it's names. Here's a quick example showing you what I mean
def firstThing(): # this could be your 'cd' task
print 'ran first task'
def secondThing(): # another task you would want to run
print 'ran second task'
def showCommands(): # a task to show available commands
print functionDict.keys()
# a dictionary mapping commands to functions (you could do the same with classes)
functionDict = {'f1': firstThing, 'f2': secondThing, 'help': showCommands}
# the actual function that gets the input
def main():
cont = True
while(cont):
selection = raw_input('enter your selection ')
if selection == 'q': # quick and dirty way to give the user a way out
cont = False
elif selection in functionDict.keys():
functionDict[selection]()
else:
print 'my friend, you do not know me. enter help to see VALID commands'
if __name__ == '__main__':
main()
Related
I'm working on a piece of code in Python 3 that acts as an interface for various dead by daylight cheats. I'm using a very basic setup, just input() and os.system() to find and open specific files. It works fine, but there's one small issue.
The interface uses cmd prompt, and I have it set up so that entering numbers 1-4 will open programs and executables used to modify the game. However, some of the programs are required to stay open while others run. For example, the BVHR Session Grabber must be running along with the SaveInjector Interface, because the SaveInjector needs to receive a certain code from the Grabber.
There's a problem here, the code is set up in such a way that you can only run one file at a time. I'm not sure what exactly causes this, but I'll try to explain what happens. When entering the number 1, for example, into the cmd prompt window, it opens the BHVR Session Grabber (as intended). After that, the interface becomes unusable until I close the BHVR Session Grabber. I can't type anything into it while it's active, so I can't open multiple programs at once.
Not entirely sure if this is intended or not, but I'm hoping it's avoidable. If anyone has any knowledge on the issue let me know how to find a way around this in the comments please.
import os.path
def interface():
os.system('cls' if os.name == 'nt' else 'clear')
print("""
\n\nSelect a cheat below:
\n
\n1: BHVR Session Grabber
\n2: SaveInjector Interface
\n3: Rank / Shards Editor
\n4: Exit\n
""")
def checker():
interface()
lst = ['1','2','3','4']
good_input = input(">")
global user_input
user_input = None
while not user_input:
if good_input in lst:
user_input = good_input
else:
print("Enter a valid integer.")
good_input = input(">")
checker()
cwd = os.getcwd()
def selection():
if user_input == '1':
f = (os.path.join(cwd, 'Programs', 'BHVRSession', 'CookieFinder.exe'));
os.system(f)
checker()
selection()
elif user_input == '2':
os.system('cmd /k "cd Programs & cd Injector & SI.exe & cd.. & cd.. & Ultimate.py"')
elif user_input == '3':
f = (os.path.join(cwd, 'Programs', 'RankShards', 'Sender.exe'));
os.system(f)
checker()
selection()
elif user_input == '4':
os.system('cmd /k "taskkill/im py.exe"')
selection()
The problem here is that os.system() is blocking. This means that it will only return and continue executing your Python code after the program it runs finishes. Instead, you should look at the subprocess package to learn how to fork a new process that can run in parallel with your Python program.
I have a python script that runs and accepts user input to make decisions. Based on the input I would like to give the user control of the python repl. Here is an example:
def func():
# hand over control to the user
breakpoint()
while True:
print('What would you like to do?\nq: quit\ni: interact')
i = input()
if i=='q':
break
elif i=='i':
func()
else:
print(f'invalid command: {i}')
Calling this code snippet with for example ipython3, the user is prompted for input. When the user presses i, func() is called, at which point I would like the user to be able to type python commands such as print(i).
My current best solution is to then set a breakpoint, the user may then need to type r to get to the right frame and then must then type interact. This is nearly acceptable, but I would like my user to not need to know that I'm using a debugger to give them interactive control, rather I would like them to be given an ipython prompt directly.
I looked at this post from 10 years ago: Jump into a Python Interactive Session mid-program? rz.'s comment looks interesting, but it looks like too much has changed for me to use his answer as is, plus there may be newer ways of doing things.
I am making a program witch is basically a terminal interface to a couple of math libraries that i made for school. the flow is an infinite loop in python terminal that gives you the option to call a function in the library, add values and get an answer.
The thing is that i would like to make the code less shaky buy being able to call a help input and for that i would like to make a list of all available commands.
Or even better show the different categories and make it possible to write sub helps like for example
>>> help
algebra
finance
geometry
>>>help.finance
stockmarket
personal finance
>>>help.finance.stockmarket
what: price to earnings. command: "p2e" values: stockpice, eps
note: this is just some sudo scenario i just created but something like that would work.
For now i have created if statements, but when porting in all my different libraries and categories is the the code quickly becomes repetitive.
i also now have it that if you type "help" you get every single command just out of the blue.
print("Welcome to the stockmath project ")
print("if you want to run a command just type it in below")
print("if you dont know any commands, type help")
print("_______________________________________________")
command = input()
while True:
if command == ("stm.test"):
stockmath.test()
elif command == ("help") and counter == 0:
print ("p2e, price to earnings,command = stm.p2e,"
"values: price per share, earnings per share")
elif command == ("quit"):
break
I would just again remind you that i have not built this part yet.
Use the python module cmd.
Here is a very basic example
import cmd
class SimpleCmd(cmd.Cmd):
intro = 'Welcome to this simple command prompt'
prompt = ">>"
def do_left(self,arg):
"""Go Left"""
print("Go Left")
def do_right(self,arg):
"""Go Right"""
print("Go Right")
def do_quit(self,arg):
"""Exit command prompt"""
return True
if __name__ == '__main__':
SimpleCmd().cmdloop()
The output of the program will look something like this
Welcome to this simple command prompt
>>help
Documented commands (type help <topic>):
========================================
help left right
>>help left
Go Left
The cmd module takes care of the infinite loop for you and will do a lot of the complex stuff like parsing the help documentation and providing a command history using the and arrow keys.
I am in the middle of programming a MUD like game, more for the experience and practice. I am trying to find an algorithm that will effectively prase text commands. If you have played MUD type games before you know what I am talking about. If not and example would be if I typed in the command: 'search' it would execute the 'search' whether you type in s, se, sea, sear, searc, search, etc...
Now I do have a algorithm already established, but the more I think about it the more problems see to arise. In code it goeslike this:
def text_parser(string, command):
string_list = []
command_list = []
for x in string:
string_list.append(x)
for x in command:
command_list.append(x)
if len(string_list) == 0: # checks to see if user have entered anything
return False
if ((string_list > command_list) - (string_list < command_list)) is 1: # returns false if string has more items than command
return False
else:
if string_list[:len(string_list)] == command_list[:len(string_list)]:
return True
else:
return False
And you can call this function by:
if text_parser('hel', 'hello') is True:
print('This returns True')
if text_parser('hel', 'Foo') is True:
print('This returns False')
Now this code works perfectly.. exactly what I need for it to do. If I type in 'se' and its other end-members for the command' search' it will always be true... but now comes my biggest problem.. Say i have two commands:
'quit' and 'quaff' and the user only inputs 'qu'
According to my algorithm it will execute both the 'quit' and the 'quaff', because my code is set up as:
if (text parser check):
blah
if (text parser check):
blach
etc.... # The only way out of this is to do nested if's and elif's.. which will look messy..
Which is not what I want to do at all. As you can see many more problems can arise the more commands you set up with the game.
What will be a good algorithm set up for text parsing? Or do I just need to change a few things in my already existing code to address the bugs that can pop up with this set up...? Thanks
I think your approach can be simplified by having a list of all available commands. And then define a function that will parse your input string and look for a command match like this:
all_commands = ['search', 'quit', 'quaff']
def find_command(string, allowed_commands=None):
if allowed_commands is None:
# if there is no restrictions, look for all commands
allowed_commands = all_commands
matching_commands = []
for command in commands:
if command.startswith(string):
matching_commands.append(command)
if len(matching_commands) == 1:
# found a match
return matching_commands[0]
# found either no match or more than one
return None
Now, the function find_command will find matches for the input string and it will either match all commands (all_commands) or a given subset (allowed_commands), in case you only want to allow certain commands in that situation.
For example:
print find_command('se') # returns search
print find_command('search') # returns search
print find_command('qu') # returns None
print find_command('quaf') # returns quaff
print find_command('qu', ['search', 'quit']) # returns quit
Did you try pyparsing? It looks good for such tasks. Check examples: http://pyparsing.wikispaces.com/Examples
You might want to consider the cmd module, which lets you define commands as methods on a class. It then provides a prompt where you can type the commands and see the results. The parsing is fairly rudimentary, but probably sufficient for you to get started.
cmd was featured on Python Module of the Week a while ago, and it has a very nice tutorial. Here's just a very brief taste:
import cmd
class HelloWorld(cmd.Cmd):
"""Simple command processor example."""
def do_greet(self, person):
"""greet [person]
Greet the named person"""
if person:
print "hi,", person
else:
print 'hi'
def do_EOF(self, line):
return True
def postloop(self):
print
if __name__ == '__main__':
HelloWorld().cmdloop()
When you run the above code you'll get a prompt where you can type commands. For example:
(Cmd) greet
hi
(Cmd) greet bob
hi, bob
(Cmd)
The module provides the command loop, and it also supports autocompletion, live help, a customizable prompt, and several other features.
Perhaps, put your commands in a list, and do
def parse(userInput):
returnList = []
for cmd in commandList:
if userInput in cmd:
cmdList.append(cmd)
return returnList
Then you have matching commands in your returned list.
I'm making a text-based game and need an application-wide command line that's able to be pulled up at any text entry. My plan was to have the commands contained within a module, and execute command(), which would then allow the user to enter a command (or get a list) that is then run (contained within the same module). This didn't work because I need a way to return to where the user was. Is there anyway to return to where the user was before they entered command mode, or is there a better way to do this?
This was my idea:
import commands
def something():
print "a question"
action = raw_input("> ")
if action == "command":
commands.commands()
elif "something else" in action:
do something
else:
error.error(1)
something()
Which then went to commands.py:
def commands():
print "Enter a command, help for a list, blah blah blah."
command = raw_input("$ ")
if command == "bag":
bag()
elif command == "other":
other()
def bag():
print "Action listing things in bag"
The problem is returning where the user left off.
What you need is a main game loop:
while game.is_running:
command = get_user_input()
user_do(command)
update_world()
This will repeat the three lines of code inside the while loop for as long as game.is_running is True. First, you get the user input. Next, you act on it. Finally, you perform any other updates your game needs, like moving or spawning monsters. At this point, it loops back and asks the user for another command.
Update: here is a working example:
# In commands.py:
def bag():
print 'bag'
def other():
print 'other'
def unrecognized():
print 'unknown command'
# In main.py:
import commands
def user_input():
print 'a question'
return raw_input('>')
def user_do(command):
# get the matching command out of commands, or pass back
# the unrecognized function if it's not found
action = getattr(commands, command, commands.unrecognized)
action()
is_running = True
while is_running:
command = user_input()
if command == 'quit':
is_running = False
else:
user_do(command)
In this example, I've cheated and am relying on the user input commands being identical to the name of the functions to be called. In user_do, the getattr call compares the string the user has input with the contents of the command module, returning the function of the same name if one exists, or the fallback function unrecognized if it doesn't. action will now either hold the command function or unrecognized.
If you don't want to have your user commands so tightly bound to the actual functions themselves, you can use a dict as a branching construct (or dispatch) instead of having a lot of if / elif / else statements:
# Modified main.py
import commands
COMMAND_DISPATCH = {
'bag': commands.bag,
'sack': commands.bag,
'other': commands.other,
# ...
}
# ...
def user_do(command):
action = COMMAND_DISPATCH.get(command, commands.unrecognized)
action()
In this example, rather than look up the functions in the commands module, we look them up in COMMAND_DISPATCH instead.
One more bit of advice: pretty soon you'll want to look at parsing the user input into more than just a single command. For this example, let's assume you want to be able to accept input of the form "command ... ". You can extend the user_input function to take care of this:
def user_input():
print 'a question'
user_input = raw_input('>').split(' ')
command = user_input[0]
arguments = user_input[1:]
return command, arguments
So if you enter 'foo bar baz', this would return the tuple ('foo', ['bar', 'baz']). Next we update the main loop to deal with the arguments.
while is_running:
# use tuple unpacking to split into command, argument pairs
command, arguments = user_input()
if command == 'quit':
is_running = False
else:
user_do(command, arguments)
Then make sure we pass them to the command:
def user_do(command, arguments):
action = COMMAND_DISPATCH.get(command, commands.unrecognized)
action(arguments)
And finally, we modify the commands to accept and handle the arguments:
def bag(arguments):
for argument in arguments:
print 'bagged ', argument
For a text adventure, you'll want a more substantial parser, something that deals with command object, command object preposition subject, and possibly even command adjective object ....
You should research "python finite state machine". It is pretty much exactly what you want.
Charming Python: Using state machines
Finite-state machine
wiki.python.org/moin/FiniteStateMachine
What is a state machine?
An overly accurate description of a state machine is that it is a
directed graph, consisting of a set of nodes and a corresponding set
of transition functions. The machine "runs" by responding to a series
of events. Each event is in the domain of the transition function
belonging to the "current" node, where the function's range is a
subset of the nodes. The function returns the "next" (perhaps the
same) node. At least one of these nodes must be an end-state. When an
end-state is reached, the machine stops.
When to use a state machine ...
Start in an initial state.
Read a line of input.
Depending on the input and the current state, either transition to a new state or process the line as appropriate for the current state.
Similar to what #MatthewTrevor suggested in his answer, you would have a main loop, and pass a "state" context to the first entry point call (start or intro or whatever). That call can change the state context to point at something else. When control reaches back to the main loop again and it checks the state, it will run the new state.