I was doing some research about Python.
And I saw something like this.
# Start CLI-Loop
while True:
try:
text = raw_input()
except:
text = error()
if text == condition_1:
do_Some_Other_Things_1()
break
elif text == condition_2:
do_Some_Other_Things_2()
Is CLI-Loop stands for "Command Line Interface Loop" ?
If not, what does it mean?
What's so special about it?
There is nothing special about the loop; the author simply introduces the code block, stating that it'll interpret commands.
Which is exactly what the loop does; using raw_input(), it asks for user input from the terminal, then executes functions based on the input. In other words, it takes commands, interfacing with the user.
CLI indeed stands for Command Line Interface. There's nothing special about this loop, it's just called "the CLI loop" to indicate it's a loop handling the input taken from the command line.
Related
I am working on a simple Python program where the user enters text and it says something back or executes a command.
Everytime I enter a command, I have to close the program. Python doesn't seem to have a goto command, and I cannot enter more than one "elif" without an error.
Here is the part of the code that gives me an error if I add additional elif statements:
cmd = input(":")
if cmd==("hello"):
print("hello " + user)
cmd = input(":")
elif cmd=="spooky":
print("scary skellitons")
Here's a simple way to deal with different responses based on user input:
cmd = ''
output = {'hello': 'hello there', 'spooky': 'scary skellitons'}
while cmd != 'exit':
cmd = input('> ')
response = output.get(cmd)
if response is not None:
print(response)
You can add more to the output dictionary, or make the output dictionary a mapping from strings to functions.
Your program is only coded to execute once from what you've posted. If you want it to accept and parse the user input multiple times, you'll have to explicitly code that functionality it.
What you want is a while loop. Take a look at this page for a tutorial and here for the docs. With while, your program would have the general structure of:
while True:
# accept user input
# parse user input
# respond to user input
while statements are part of the larger flow control.
1.I'm using break to break out of a loop, but I don't know how to make the program keep going no matter what unless this happens. Just typing in while: is invalid (or so the progam tells me) and I want the game to keep going even if the user types in an emptry string.
2.Is there a way to not have to re-type a bit of code every time I need it? I have a bunch of responses for the program to spit out that I'll have to use many times:
if action[0]=='go':
print("You're supposed to go to David!")
elif action[0]=='look':
print("You can't see that")
elif action[0]=='take':
print("You don't see the point in taking that.")
else:
print("I don't recognise that command")
Where action is a list from the player's input. Or do I just have to type it out again each time?
I don't know how to define a function that does the above, and I'm not even sure that's what I'm supposed to do.
3.Some story descriptions I'm using are a very long stings and I don’t want players to have to scroll sideways too much. But I want to just define them as variables to save myself some typing. Is there a way around this. Or do I just have to type it out every time with
print(“““a string here”””)
4.If the string starts with 'look' and has 'floor' or 'mess' or 'rubbish' in it, I want it to print a certain output. This is what I currently have:
if action[0]=='look':
if 'floor' in action or 'rubbish' in action or 'trash' or 'mess' in action:
print('onec')
elif 'screen' in action or 'computer' in action or 'monitor' in action:
print('oned')
elif 'around' in action or 'room' in action or 'apartment' in action:
print('onee')
elif 'david' in action or 'tyler' in action or 'boy' in action or 'brat' in action or 'youth' in action:
print('onef')
break
else:
print("You can't see that")
It prints 'onec' for any input beginning with 'look'.
The while statement requires a condition.
You can call the same instructions over and over using a function.
"String literals can span multiple lines in several ways"
Use strategically-placed print statements to show the value of action, e.g. after if action[0]=='look'
Lastly, please don't add any more items to this question. Rather ask a new question. This site has somewhat specific rules on that sort of thing.
To make an infinite While loop, use while True:.
You could use a dict to store common action strings and their responses.
Just register the string first, then when the input come, change it:
command = "nothing"
command = input("Enter command: ")
while command:
Or just simply:
while True:
Yes, think about it by yourself.. Okay, why not put it in list responses?
If it is really long, put it in a file. Read it when you need it using open(). More on File Processing
This will help you shorten your code, making it easier to read, and makes it more efficient.
while requires a condition that it has to evaluate. If you want it to loop forever, just give it a condition that always evaluates to True, such as 4>3. It would be best for everyone if you just used while True:, which is the clearest option.
For this specific case, I would recommend using a dict() and its .get() method. Something like this:
action_dict = {'go':"You're supposed to go to David!",
'look':"You can't see that",
'take':"You don't see the point in taking that."
}
print(action_dict.get(action[0], "I don't recognise that command")
would replicate what you have going on right now.
See the link provided by cjrh here: http://docs.python.org/3.3/tutorial/introduction.html#strings
Our mind-reading powers are a bit off in October, we'll need some more information other than "it does not work" to help you with that.
I have the following function:
def getInput():
# define buffer (list of lines)
buffer = []
run = True
while run:
# loop through each line of user input, adding it to buffer
for line in sys.stdin.readlines():
if line == 'quit\n':
run = False
else:
buffer.append(line.replace('\n',''))
# return list of lines
return buffer
which is called in my function takeCommands(), which is called to actually run my program.
However, this doesn't do anything. I'm hoping to add each line to an array, and once a line == 'quit' it stops taking user input. I've tried both for line in sys.stdin.readlines() and for line sys.stdin, but neither of them register any of my input (I'm running it in Windows Command Prompt). Any ideas? Thanks
So, took your code out of the function and ran some tests.
import sys
buffer = []
while run:
line = sys.stdin.readline().rstrip('\n')
if line == 'quit':
run = False
else:
buffer.append(line)
print buffer
Changes:
Removed the 'for' loop
Using 'readline' instead of 'readlines'
strip'd out the '\n' after input, so all processing afterwards is much easier.
Another way:
import sys
buffer = []
while True:
line = sys.stdin.readline().rstrip('\n')
if line == 'quit':
break
else:
buffer.append(line)
print buffer
Takes out the 'run' variable, as it is not really needed.
I'd use itertools.takewhile for this:
import sys
import itertools
print list(itertools.takewhile(lambda x: x.strip() != 'quit', sys.stdin))
Another way to do this would be to use the 2-argument iter form:
print list(iter(raw_input,'quit'))
This has the advantage that raw_input takes care of all of the line-buffering issues and it will strip the newlines for you already -- But it will loop until you run out of memory if the user forgets to add a quit to the script.
Both of these pass the test:
python test.py <<EOF
foo
bar
baz
quit
cat
dog
cow
EOF
There are multiple separate problems with this code:
while run:
# loop through each line of user input, adding it to buffer
for line in sys.stdin.readlines():
if line == 'quit':
run = False
First, you have an inner loop that won't finish until all lines have been processed, even if you type "quit" at some point. Setting run = False doesn't break out of that loop. Instead of quitting as soon as you type "quit", it will keep going until it's looked at all of the lines, and then quit if you typed "quit" at any point.
You can fix this one pretty easily by adding a break after the run = False.
But, with or without that fix, if you didn't type "quit" during that first time through the outer loop, since you've already read all input, there's nothing else to read, so you'll just keep running an empty inner loop over and over forever that you can never exit.
You have a loop that means "read and process all the input". You want to do that exactly once. So, what should the outer loop be? It should not be anyway; the way to do something once is to not use a loop. So, to fix this one, get rid of run and the while run: loop; just use the inner loop.
Then, if you type "quit", line will actually be "quit\n", because readlines does not strip newlines.
You fix this one by either testing for "quit\n", or stripping the lines.
Finally, even if you fix all of these problems, you're still waiting forever before doing anything. readlines returns a list of lines. The only way it can possibly do that is by reading all of the lines that will ever be on stdin. You can't even start looping until you've read all those lines.
When standard input is a file, that happens when the file ends, so it's not too terrible. But when standard input is the Windows command prompt, the command prompt never ends.* So, this takes forever. You don't get to start processing the list of lines, because it takes forever to wait for the list of lines.
The solution is to not use readlines(). Really, there is never a good reason to call readlines() on anything, stdin or not. Anything that readlines works on is already an iterable full of lines, just like the list that readlines would give you, except that it's "lazy": it can give you the lines one at a time, instead of waiting and giving you all of them at once. (And even if you really need the list, just do list(f) instead of f.readlines().)
So, instead of for line in sys.stdin.readlines():, just do for line in sys.stdin: (Or, better, replace the explicit loop completely and use a sequence of iterator transformations, as in mgilson's answer.)
The fixes JBernardo, Wing Tang Wong, etc. proposed are all correct, and necessary. The reason none of them fixed your problems is that if you have 4 bugs and fix 1, your code still doesn't work. That's exactly why "doesn't work" isn't a useful measure of anything in programming, and you have to debug what's actually going wrong to know whether you're making progress.
* I lied a bit about stdin never being finished. If you type a control-Z (you may or may not need to follow it with a return), then stdin is finished. But if your assignment is to make it quit as soon as the user types "quit"< turning in something that only quits when the user types "quit" and then return, control-Z, return again probably won't be considered successful.
I want to automatically indent the next line of a console app but the user needs to be able to remove it. sys.stdout.write and print make undeletable characters and I can't write to sys.stdin (as far as I know). I'm essentially trying to get smart indenting but I can only nest deeper and deeper. Any ideas on how to climb back out?
Edit: I should have noted that this is part of a Windows program that uses IronPython. While I could do something much fancier (and might in the future), I am hoping to quickly get a reasonably pleasant experience with very little effort as a starting point.
The cmd module provides a very simple interface for creating a command line interface to your program. It might not be able to put some buffer characters in front of the next line but if you're looking for an obvious way to let your users know that the command has returned, it can provide a shell-like prompt at the beginning of each line. If you already have functions defined for your program, integrating them into a processor would be a matter of writing a handler that access the function:
import cmd
import math
def findHpyot(length, height):
return math.sqrt(length **2 + height **2)
class MathProcessor(cmd.Cmd):
prompt = "Math>"
def do_hypot(self, line):
x = raw_input("Length:")
y = raw_input("Height:")
if x and y:
try:
hypot = findHypot(float(x), float(y))
print "Hypot:: %.2f" %hypot
except ValueError:
print "Length and Height must be numbers"
def do_EOF(self, line):
return True
def do_exit(self, line):
return True
def do_quit(self, line):
return True
if __name__ == "__main__":
cmdProcessor = MathProcessor()
cmdProcessor.cmdloop()
Things to consider when writing an interactive shell using cmd
The name after do_ is the command that your users will use so that in this example, the available commands will be hypot, exit, quit, and help.
Without overriding do_help, calling help will give you a list of available commands
Any call that you want to quit the program should return True
If you want to process entries from the function call, say you wanted to be able to handle a call like "hypot 3 4" you can use the local line variable in the function call
Okay, so I'm writing a very simplistic password cracker in python that brute forces a password with alphanumeric characters. Currently this code only supports 1 character passwords and a password file with a md5 hashed password inside. It will eventually include the option to specify your own character limits (how many characters the cracker tries until it fails). Right now I cannot kill this code when I want it to die. I have included a try and except snippit, however it's not working. What did I do wrong?
Code: http://pastebin.com/MkJGmmDU
import linecache, hashlib
alphaNumeric = ["a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z","A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z",1,2,3,4,5,6,7,8,9,0]
class main:
def checker():
try:
while 1:
if hashlib.md5(alphaNumeric[num1]) == passwordHash:
print "Success! Your password is: " + str(alphaNumeric[num1])
break
except KeyboardInterrupt:
print "Keyboard Interrupt."
global num1, passwordHash, fileToCrack, numOfChars
print "What file do you want to crack?"
fileToCrack = raw_input("> ")
print "How many characters do you want to try?"
numOfChars = raw_input("> ")
print "Scanning file..."
passwordHash = linecache.getline(fileToCrack, 1)[0:32]
num1 = 0
checker()
main
The way to allow a KeyboardInterrupt to end your program is to do nothing. They work by depending on nothing catching them in an except block; when an exception bubbles all the way out of a program (or thread), it terminates.
What you have done is to trap the KeyboardInterrupts and handle them by printing a message and then continuing.
As for why the program gets stuck, there is nothing that ever causes num1 to change, so the md5 calculation is the same calculation every time. If you wanted to iterate over the symbols in alphaNumeric, then do that: for symbol in alphaNumeric: # do something with 'symbol'.
Of course, that will still only consider every possible one-character password. You're going to have to try harder than that... :)
I think you're also confused about the use of classes. Python does not require you to wrap everything inside a class. The main at the end of your program does nothing useful; your code runs because it is evaluated when the compiler tries to figure out what a main class is. This is an abuse of syntax. What you want to do is put this code in a main function, and call the function (the same way you call checker currently).
Besides printing, you need to actually exit your program when capturin KeyboardInterrupt, you're only printing a message.
This is what worked for me...
import sys
try:
....code that hangs....
except KeyboardInterrupt:
print "interupt"
sys.exit()
Well, when you use that try and except block, the error is raised when that error occurs. In your case, KeyboardInterrupt is your error here. But when KeyboardInterrupt is activated, nothing happens. This due to having nothing in the except part. You could do this after importing sys:
try:
#Your code#
except KeyboardInterrupt:
print 'Put Text Here'
sys.exit()
sys.exit() is an easy way to safely exit the program. This can be used for making programs with passwords to end the program if the password is wrong or something like that. That should fix the except part. Now to the try part:
If you have break as the end of the try part, nothing is going to happen. Why? Because break only works on loops, most people tend to do it for while loops. Let's make some examples. Here's one:
while 1:
print 'djfgerj'
break
The break statement will stop and end the loop immediately unlike its brother continue, which continues the loop. That's just extra information. Now if you have break in a something like this:
if liners == 0:
break
That's going to depend where that if statement is. If it is in a loop, it is going to stop the loop. If not, nothing is going to happen. I am assuming you made an attempt to exit the function which didn't work. It looks like the program should end, so use sys.exit() like I showed you above. Also, you should group that last piece of code (in the class) into a seperate function. I hope this helps you!