I am relatively new to Python and programming in general. I am working on writing a console application.
How do you write a console application that accepts commands in a terminal? For instance, like how a terminal itself accepts commands and does a corresponding task. Are the "commands" actually just functions in the application that are called by the user? Is the console interface itself just a function? E.g. :
def console_interface():
user_input = input()
if user_input == "some_function":
some_function()
if user_input == "some_other_function":
some_other_function()
Although it is not efficient, I know the above works because I have tested it. Is this general idea correct or is it way off?
Python's standard library offers a module that encapsulates exactly the "console application that accepts commands" functionality: see https://docs.python.org/3/library/cmd.html .
In that module, the commands are actually methods of your class, which subclasses cmd.Cmd: do_this, do_that, etc, by naming convention. The example at https://docs.python.org/3/library/cmd.html#cmd-example is a rich "console accepting commands" for turtle graphics, so you can play with it.
Didactically, you may want to start with far simpler examples given at http://pymotw.com/2/cmd/ -- that's Python 2 but the functionality is just about the same. The excellent series of examples need a little adaptation to run in Python 3, but it shouldn't be too hard.
For example, consider the very first one:
import cmd
class HelloWorld(cmd.Cmd):
"""Simple command processor example."""
def do_greet(self, line):
print "hello"
def do_EOF(self, line):
return True
if __name__ == '__main__':
HelloWorld().cmdloop()
The do_EOF is what happens when the user terminates standard input (control-D on Unix); as https://docs.python.org/3/library/cmd.html#cmd.Cmd.cmdloop says,
An end-of-file on input is passed back as the string 'EOF'.
(In this case, the return True terminates the program).
The only thing you need to change to run this in Python 2 rather than 3 is the one line:
print "hello"
which must become
print("hello")
because print, which was a statement in Python 2, is now a function in Python 3.
I find the cmd.py sources at http://www.opensource.apple.com/source/python/python-3/python/Lib/cmd.py to also be quite instructive and I would recommend studying them as an introduction to the world of "dispatching"...!
Related
Here is a python script that sends its output to different places depending on whether it was run interactively or imported as a module.
# main.py
def main():
output = "... do some processing ..."
if __name__ == "__main__":
print("sending output to stdout")
#print(output)
else:
print("sending output to file")
#write_to_file(output)
if __name__ == "__main__":
main()
A different path runs depending on how the script is called:
$ python main.py
sending output to stdout
$ python
>>> import main
>>> main.main()
sending output to file
The code works as expected, but I feel like it could be a code smell. I can see reasons why multiple of these checks in a single script is both good and bad and I am looking for feedback as to whether or not this is pythonic.
Reasons why it may be pythonic
There is precedent in other languages for using similar constructs (like #ifdef DEBUG in c++)
This method does not introduce another variable into main()'s parameter list (see #3 under Cons.)
Reasons why it may be unpythonic
I have not seen multiple if __name__ == "__main__": statements in production code or in any code examples (although my search was not exhaustive.)
The python 3 documentation for __main__ does not include any examples that promote this coding style. There are only mentions to the common way it is used. Exclusion from the doc does not mean it is bad, just that the style is uncommon.
The same objective can be achieved, probably with less confusion to newer python developers, by passing an argument such as output="file" to main()
I hope this question is not too opinion-based for SO. Feel free to quote from the Zen of Python to support your answer if you wish. I look forward to your feedback.
I am writing a Python interpreter and want to redirect the function's return values to stdout, like the Python Interpreter in Interactive Mode. Within this mode, when the user calls a function, its return value is printed on the screen. The same occurs with expressions.
E.g.
>>> foo()
'Foo return value'
>>> 2+4
6
>>> print('Hello!')
'Hello!'
Changing the sys.stdout only affects the print function. How do I redirect the other expressions to stdout?
Thank you
First, the interactive mode does not print the return value from any function called. Instead, it prints the result of whatever expression the user typed in. If that's not a function call, it still gets printed. If it has 3 function calls in it, it still prints one result, not 3 lines. And so on.
So, trying to redirect function return values to stdout is the wrong thing to do.
What the interactive interpreter does is something sort of like this:
line = raw_input(sys.ps1)
_ = eval(line)
if _ is not None:
print repr(_)
(You may notice that you can change sys.ps1 from the interactive prompt to change what the prompt looks like, access _ to get the last value, etc.)
However, that's not what it really does. And that's not how you should go about this yourself either. If you try, you'll have to deal with complexities like keeping your own globals separate from the user's, handling statements as well as expressions, handling multi-line statements and expressions (doing raw_input(sys.ps2) is easy, but how do you know when to do that?), interacting properly with readline and rlcomplete, etc.
There's a section of the documentation called Custom Python Interpreters which explains the easy way to do this:
The modules described in this chapter allow writing interfaces similar to Python’s interactive interpreter. If you want a Python interpreter that supports some special feature in addition to the Python language, you should look at the code module.
And code:
… provides facilities to implement read-eval-print loops in Python. Two classes and convenience functions are included which can be used to build applications which provide an interactive interpreter prompt.
The idea is that you let Python do all the hard stuff, up to whatever level you want to take over, and then you just write the part on top of that.
You may want to look at the source for IDLE, ipython, bpython, etc. for ideas.
Instead of using exec() to run the user input, try eval():
retval = eval(user_input)
sys.stdout.write(repr(retval) + "\n")
At the very beginning of the Python Script, I have defined a lot of variables. For instance:
cmd_attack = "attack"
cmd_protect = "protect"
cmd_help = "help"
cmd_help works in a user menu function shown here:
def usermenu():
um_in=raw_input('Menu :: ')
#Help Command
if um_in.lower()==cmd_help.lower():
print(helplist)
usermenu()
That is successful - it prints the help list and then returns to the raw input. However, when I do something similar involving cmd_help in another function...
def tf_elf_battle_merc():
battleinput==raw_input('Elf :: ')
global cmd_help
global cmd_attack
global cmd_protect
if battleinput.lower()==cmd_attack.lower():
attack_merc()
elif battleinput.lower()==cmd_help.lower():
print(tf_elf_help)
That does nothing, prints no errors, and returns to the shell line - without printing anything or going anywhere. I used global commands because I was testing out possible solutions to the problem.
The order that these are put in is the CMD functions at the top, the tf_elf_battle_merc() in the middle, and the usermenu() last. I have tried a few things and the related questions haven't helped... any thoughts? I'm kind of new to Python. If you're curious, it is script where you can log in and play text-type games.
The full script is here on Pastebin.
Thank you in advance!
Edit: If you download and run the script - use "Guest" (case-sensitive) as a username and you'll be let into it
Your code (with some edits, seen below) worked fine for me after changing battleinput==raw_input('Elf :: ') to battleinput=raw_input('Elf ::'), you don't want to compare them, you want to define battleinput.
However, it should raise an error of that, since battleinput is not defined, yet you're trying to comparing it: if battleinput.lower() == ....
Also you're mixing Python 3 and Python 2? Using raw_input() from Python 2, yet print("asd") from Python 3, instead of Python 2's print "asd"?
Everything looks like your code is never reached, the problem is elsewhere.
Here's the code for Python 3, which works fine:
cmd_attack = "attack"
cmd_protect = "protect"
cmd_help = "help"
def tf_elf_battle_merc():
battleinput=input('Elf :: ') # Use raw_input() for Python 2
# You don't need the globals here
if battleinput.lower()==cmd_attack.lower():
print("attack")
elif battleinput.lower()==cmd_help.lower():
print("help")
tf_elf_battle_merc()
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
What does <if name==“main”:> do?
I have wrote scripts in Python for quite a while now and I study more of Python as I need it. When reading other people's code I meet if name == "__main__": construct quite often.
What is it good for?
This allows you to use the same file both as a library (by importing it) or as the starting point for an application.
For example, consider the following file:
# hello.py
def hello(to=__name__):
return "hello, %s" % to
if __name__ == "__main__":
print hello("world")
You can use that code in two ways. For one, you can write a program that imports it. If you import the library, __name__ will be the name of the library and thus the check will fail, and the code will not execute (which is the desired behavior):
#program.py
from hello import hello # this won't cause anything to print
print hello("world")
If you don't want to write this second file, you can directly run your code from the command line with something like:
$ python hello.py
hello, __main__
This behavior all depends on the special variable __name__ which python will set based on whether the library is imported or run directly by the interpreter. If run directly it will be set to __main__. If imported it will be set to the library name (in this case, hello).
Often this construct is used to add unit tests to your code. This way, when you write a library you can embed the testing code right in the file without worrying that it will get executed when the library is used in the normal way. When you want to test the library, you don't need any framework because you can just run the library as if it were a program.
See also __main__ in the python documentation (though it's remarkably sparse)
Basically,
There's a distinction between the "main" script file and external files which were imported or referenced in another way. If the script is the "main" script then the special variable __name__ will equal "__main__".
You can use this to protect the "execution" code from the classes and variables the script has. This enables you to import a script and use classes and variables without actually running that script's main code if it has any.
See also: What does if name == “main”: do?
I've seen a couple of Python IDE's (e.g. PyDev Extensions, WingIDE) that provide a debug console - an interactive terminal that runs in the context of the method where the breakpoint is. This lets you print members, call other methods and see the results, and redefine methods to try to fix bugs. Cool.
Can anyone tell me how this is implemented? I know there's the Code module, which provides an InteractiveConsole class, but I don't know how this can be run in the context of currently loaded code. I'm quite new to Python, so gentle assistance would be appreciated!
You could try looking at the python debugger pdb. It's like gdb in how you use it, but implemented in pure python. Have a look for pdb.py in your python install directory.
Right, I'm ashamed to admit it's actually in the documentation for InteractiveConsole after all. You can make it run in the local context by passing in the result of the locals() function to the InteractiveConsole constructor. I couldn't find a way to close the InteractiveConsole without killing the application, so I've extended it to just close the console when it catches the SystemExit exception. I don't like it, but I haven't yet found a better way.
Here's some (fairly trivial) sample code that demonstrates the debug console.
import code
class EmbeddedConsole(code.InteractiveConsole):
def start(self):
try:
self.interact("Debug console starting...")
except:
print("Debug console closing...")
def print_names():
print(adam)
print(bob)
adam = "I am Adam"
bob = "I am Bob"
print_names()
console = EmbeddedConsole(locals())
console.start()
print_names()
http://docs.python.org/3.0/library/functions.html#input
http://docs.python.org/3.0/library/functions.html#eval
def start_interpreter():
while(True):
code = input("Python Console >")
eval(code)
I'm sure, however, that their implementation is much more foolsafe than this.
Python has a debugger framework in the bdb module. I'm not sure if the IDE's you list use it but it's certainly possible to implement a full Python debugger with it.
If you want to experiment with your own Python console then this is a nice start:
cmd = None
while cmd != 'exit':
cmd = raw_input('>>> ')
try:
exec(cmd)
except:
print 'exception'
But for real work use the InteractiveConsole instead.