Python (unbound method wrongCommand.wrong) - python

Am currently having a bit of trouble with my code. I am making a very basic RPG, and have came across this problem:
(unbound method wrongCommand.wrong)
Am also running python 2.7.5, and windows 7.
Here's my code:
import os
class wrongCommand():
def wrong():
os.system("cls")
print "Sorry, the command that you entered is invalid."
print "Please try again."
def main():
print "Welcome to the game!"
print "What do you want to do?"
print "1.) Start game"
print "2.) More information/Credits"
print "3.) Exit the game"
mm = raw_input("> ")
if mm != "1" and mm != "2" and mm != "3":
print wrongCommand.wrong
main();
main()

So first, you'd want to change
print wrongCommand.wrong
To
print wrongCommand.wrong()
(Note: addition of open and close parens)
But then you'd get the lines printed from the wrong method as well as the return value of that method, which is currently None.
So then I'd probably change
print wrongCommand.wrong()
To simply
wrongCommand.wrong()
(Note: dropping of the print statement)
Alternatively, you could have wrong() return a string, rather than print one, and then this line
print wrongCommand.wrong()
Would be fine.
You will either have to call the wrong() method off of a class instance, e.g.
wc = wrongCommand() # Create a new instance
wc.wrong()
or simply
wrongCommand().wrong()
In either case you'll have to change your wrong() method definition to
def wrong(self):
#...
Or you'll get an error like "wrong() expects exactly 1 argument, got none".
Or you can define the wrong method as a class method or static method:
#staticmethod
def wrong():
# ...
or
#classmethod
def wrong(cls):
#...

Related

Exit from subfunction of function to main

#!/usr/bin/env python
class Functions() :
def A(self):
print "hey"
self.B()
return 1
def B(self):
print "hello"
exit(0)
func_obj = Functions()
def main() :
A = func_obj.A()
print A
print "awesome"
if __name__ == '__main__' :
main()
Above is my code. What I'm trying to do is that I want to call functionA from the main() function and when functionA executes functionB, I want functionB to raise error and exit back to the main() function without going back to functionA. How can I achieve this? Basically I want the main function to print "awesome" after functionB exits. I'm not sure what is the correct keyword to look it up.
What you're looking for are exceptions - they are actually designed to do just this: break the normal flow of execution and propagate up the call stack until someone take care of them (as a last resort, the runtime will catch them, display the error message and a full traceback, and exit).
There are two parts to the process: first raising the exception, then catching it at the right place. In your example it might look like:
# declare our own exception type so we can catch specifically this one
class MyOwnException(Exception):
pass
def a():
print("in a - before b")
b()
print("in a - after b (shouldn't see this)")
def b():
print("in b, before raise")
raise MyOwnException("hello houston ?")
print("in b, after raise (shouldn't see this)")
if __name__ == "__main__":
print("calling a")
try:
a()
print("after a (shouldn't see this)")
except MyOwnException as e:
print("caugth error {}".format(e))
FWIW, your example using exit() was really close since exit() actually works by raising a SysExit exception. The first and main use case for exception is of course error handling, but it's actually really a way to control the execution flow of your program (as an example the StopIteration exception is used to signal an exhausted iterator).
Hey so after someone pointed out my original answer didnt work i went searching! you can create custom exception classes to achieve what you're looking for!
class HaltException(Exception):
pass
class Functions():
def a(self):
print("hey")
self.b()
return "1"
def b(self):
print("hello")
raise HaltException("This is an exception error.")
def main():
func_obj = Functions()
try:
func_obj.a()
except HaltException as error:
print(error)
print("Awesome")
if __name__ == "__main__":
main()
This would then return the following when run :
hey
hello
This is an exception error.
Awesome

How to get first letter commands using python's cmd?

I would like to type "c" in my commandline, hit enter and have it run the "command" command. This code does what I want, but it does not use cmd. I would like to use cmd:
import sys
def command():
print("This is a command")
def quit():
print("goodbye")
sys.exit()
def take(item=None):
if item:
print("You take %s" % item)
else:
print("What would you like to take?")
commands = {
'command': command,
'quit': quit,
'take': take,
}
def complete(text, state):
print("Here is the text: %s and here is the state %s" % (text, state))
def my_loop():
while True:
c = raw_input("\n>")
if c.strip():
c = c.split(' ', 1)
for command in commands:
if command.startswith(c[0]):c[0] = command
func = commands.get(c[0], None)
if func:
if len(c) == 1:func()
else:func(c[1])
else:print("I don't understand that command")
my_loop()
Here is the same using cmd, but it does not run the "command" command when I type "c" and hit enter.
import sys, cmd
class Mcmd(cmd.Cmd):
prompt = '\n>'
def default(self, arg):
print("I do not understand that command. Type 'help' for a list of commands")
def do_command(self, line):
print("This is a command")
def do_quit(self, arg):
print("See you")
return True
Mcmd().cmdloop()
How can I get the start of the command to trigger the "command" or "quit" command using cmd?
("c", "co", "com", "comm"...)
all trigger the "command" function.
I was considering using the new textwrap module, but textwrap has problems being cross-platform.
Is there any other way to do this?
thank you,
You already managed to figure out how to override the default method, so you can extend that to look up a compatible method from within your Mcmd class. Try something like this:
def default(self, line):
command, arg, line = self.parseline(line)
func = [getattr(self, n) for n in self.get_names()
if n.startswith('do_' + command)]
if len(func) == 1:
return func[0](arg)
print("I do not understand that command. Type 'help' for a list of commands")
Running that
>a
I do not understand that command. Type 'help' for a list of commands
>c
This is a command
>ca
I do not understand that command. Type 'help' for a list of commands
>co
This is a command
>q
See you
While technically a duplicate of Aliases for commands with Python cmd module the answer isn't quite complete; it doesn't properly address ambiguous cases (say you got both do_command and do_copy, what should happen on the input of c and co?). Here it only returns if there is a singular match.
Alternatively Python cmd module command aliases is a possible answer, but it's just tedious.

"None" output after raw_input in Python 2.7 bug

This is a part of a text adventure that I am working on. It works fine until the user inputs any button to start, and then it prints "None". I was wondering if there was a simple way that I either am overlooking or do not know yet to prevent it from outputting "None".
def main():
print "Welcome to my Text Adventure!"
raw_input("Press any button to start!")
print main()
Function does not return anything (returns None) without explicit return statement.
def main():
print "Welcome to my Text Adventure!"
return raw_input("Press any button to start!")
As you are printing the return value by main() function, so you are supposed to return something. But you are not doing so, which results in returning "nothing", which will print "None" on the console.
Try this
def main():
return raw_input("Welcome to my Text Adventure!\nPress any button to start: ")
print main()

Interrupt raw_input in a twisted program

I will refer to this explanation and this workaround:
So what I am doing is:
def interrupted(signum, stackframe):
log.warning('interrupted > Got signal: %s', signum)
menu.quitMenu = True # to stop my code
signal.signal(signal.SIGINT, interrupted) # Handle KeyboardInterrupt
The problem is that, while the menu is notified that it must stop, and will do that soon, it can not do it now since it is stucked in a raw_input:
def askUser(self):
current_date = datetime.now().isoformat(' ')
choice = raw_input('%s > ' % current_date)
return choice
So, since twisted is removing the default interrupt handler, raw_input is not stopped. I still need to press enter after ^C for it to stop.
How can I force the raw_input to be stopped, without installing the default interrupt handler, which is a source of problems in a twisted context (since twisted itself is not expecting to be interrupted)
I guess the problem is not related to raw_input only: any function taking an unbounded time (or longer than a pre-set limit), should be interrupted somehow.
Is there an accepted twisted pattern for this?
EDIT
This is the full test code:
from datetime import datetime
class Menu:
def __init__(self):
self.quitMenu = False
def showMenu(self):
print '''
A) Do A
B) Do B
'''
def askUser(self):
current_date = datetime.now().isoformat(' ')
choice = raw_input('%s > Please select option > ' % current_date)
print
return choice
def stopMe(self):
self.quitMenu = True
def alive(self):
return self.quitMenu == False
def doMenuOnce(self):
self.showMenu()
choice = self.askUser()
if not self.alive() : # Maybe somebody has tried to stop the menu while in askUser
return
if choice == 'A' : print 'A selected'
elif choice == 'B' : print 'B selected'
else : print 'ERR: choice %s not supported' % (choice)
def forever(self):
while self.alive():
self.doMenuOnce()
from twisted.internet import reactor, threads
import signal
class MenuTwisted:
def __init__(self, menu):
self.menu = menu
signal.signal(signal.SIGINT, self.interrupted) # Handle KeyboardInterrupt
def interrupted(self, signum, stackframe):
print 'Interrupted!'
self.menu.stopMe()
def doMenuOnce(self):
threads.deferToThread(self.menu.doMenuOnce).addCallback(self.forever)
def forever(self, res=None):
if self.menu.alive() :
reactor.callLater(0, self.doMenuOnce)
else :
reactor.callFromThread(reactor.stop)
def run(self):
self.forever()
reactor.run()
Which I can run in two different ways.
Normal way:
menu = Menu()
menu.forever()
Pressing ^C stops the program immediately:
A) Do A
B) Do B
2013-12-03 11:00:26.288846 > Please select option > ^CTraceback (most recent call last):
File "twisted_keyboard_interrupt.py", line 72, in <module>
menu.forever()
File "twisted_keyboard_interrupt.py", line 43, in forever
self.doMenuOnce()
File "twisted_keyboard_interrupt.py", line 34, in doMenuOnce
choice = self.askUser()
File "twisted_keyboard_interrupt.py", line 22, in askUser
choice = raw_input('%s > Please select option > ' % current_date)
KeyboardInterrupt
As expected.
Twisted way:
menu = Menu()
menutw = MenuTwisted(menu)
menutw.run()
Pressing ^C will produce:
A) Do A
B) Do B
2013-12-03 11:04:18.678219 > Please select option > ^CInterrupted!
But askUser is actually not interrupted: I still need to press enter for raw_input to finish.
The right way to deal with this is to handle console input asynchronously, rather than trying to make a blocking input function interruptable. In other words, raw_input is fundamentally the wrong solution to the problem you're attacking.
However, if you really just want to understand what's going on here, the trick is that after calling reactor.callFromThread(reactor.stop), you have to somehow prompt raw_input to exit; it's not going to normally. However, since you're running it in a thread, it's not actually interruptable at all, because only the main thread is interruptable in Python. So I think what you want may actually be impossible. I believed that perhaps closing sys.stdin might pull the rug out from under raw_input even if it were in a thread, but it seems that the underlying libraries are doing something more clever than simply reading from the FD, so closing it does no good.

giving a command/shell type interaction in python

So say I have this graph
class Graph:
def __init__(self):
self.nodes =[]
self.edges = {}
def add_node(self,value):
self.nodes.append(value)
def is_node_present(self,node):
return True if node in self.nodes else False
Now what I want to do is something have user interact with this class..
Something like:
> g = Graph()
query executed
> g.add_node(2)
query executed
>g.is_node_present(2)
True
You know something like this.. (until user presses some secret button to quit)
How do i do this in python
Thanks
You want to look at http://docs.python.org/2/library/cmd.html as it handles the processing loop etc.
Dough Hellman http://www.doughellmann.com/PyMOTW/cmd/ is always a great resource of examples.
From Dough
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()
Example
$ python cmd_arguments.py
(Cmd) help
Documented commands (type help ):
========================================
greet
Undocumented commands:
======================
EOF help
(Cmd) help greet
greet [person]
Greet the named person
Again all from Dough Hellman :D
You can do this with raw_input()
To quit you have to press Crtl+C
A small sample script:
import readline # allows use of arrow keys (up/down) in raw_input()
# Main function
def main():
# endless command loop
while True:
try:
command = raw_input('$ ')
except KeyboardInterrupt:
print # end programm with new line
exit()
parseCommand(command)
def parseCommand(command):
print 'not implemented yet'
if (__name__ == '__main__'):
main()
Very simple python shell-like environment using exec:
cmd = raw_input("> ")
while cmd:
try:
exec(cmd)
except Exception, e:
print str(e)
cmd = raw_input("> ")
As a side note, using exec is dangerous, and should be executed only by trusted users. This allows users to run any command they wish on your system.

Categories

Resources