Is it possible to run indented blocks using exec()? - python

Using the exec() python command, is it possible to run indented blocks of code (Like if/else statements or try/except). For example:
name = input("Enter name: ")
if name == "Bob":
print("Hi bob")
else:
print("Hi user")
At the moment I am using this to run the code:
code_list = []
while True:
code = input("Enter code or type end: ")
if code == "end":
break
else:
code_list.append(code)
for code_piece in code_list:
exec(code_piece)
Also I know that this isn't very "Pythonic" or "Good practise" to let the user input their own code but it will be useful in other parts of my code.

The problem here isn't the indentation. The problem is that you're trying to exec the lines of a compound statement one by one. Python can't make sense of a compound statement without the whole thing.
exec the whole input as a single unit:
exec('\n'.join(code_list))

From exec() documentation:
This function supports dynamic execution of Python code. object must be either a string or a code object. If it is a string, the string is parsed as a suite of Python statements which is then executed ...
Thus, you can do things like
exec("a=2\nb=3")
exec("if a==2:\n\tprint(a)\nelse:\tprint(b)")
You just need to follow the right syntax and indentation.

Another way of formatting code within an exec() function is to use triple quotes, which makes it easy to see what the code looks like.
code = """ # Opening quotes
for i in range(0, 10): # Code line 1
print(i) # Code line 2
""" # Closing quotes
exec(code)
This would maybe not work if you're asking the user to input the code, but it's a trick that may come in handy.

Related

What is the difference between running a code through the "console" and running it regularly?

I'm a beginner at Python and coding in general, and I've been primarily using the trinket interpreter to work out some of my scripts. I was just trying to get used to defining a function with if and elif lines alongside the return command.
The code I'm trying to run is a pretty simple one, but when I run it regularly nothing shows up. However, when I run it through the console it
comes out fine. What am I doing wrong?
def the_line(text):
if text == ("just a boy"):
phrase = ("I fly alone")
elif text == "syndrome":
phrase = ("darn you syndrome")
return phrase
the_line("just a boy")
The first picture is what happens when I run it regularly and the second is through the console.
In the console, when you run a statement but don't assign it to anything, the shell will print the resulting object. You call the function but don't save it in a variable, so it is displayed. The "console" in your IDE is also called a Read, Evaluate and Print Loop (REPL).
But your code really just discarded that return value. That's what you see in the first case, the returned object wasn't assigned to anything and the object was deleted. You could assign it to a variable and print, if you want to see it.
def the_line(text):
if text == ("just a boy"):
phrase = ("I fly alone")
elif text == "syndrome":
phrase = ("darn you syndrome")
return phrase
foo = the_line("just a boy")
print(foo)
(As a side note, 4 spaces for indents please. We are not running out of spaces).
This is very clearly explained in Think Python's section 2.4. It has everything to do with the Read-Eval-Print-Loop (REPL) concept.
Briefly, the console is a REPL, so you see the output because it Prints what it Evaluated after Reading something (and then it prompts again for you to input something, that's the loop part). When you run the way you call "regularly", you are in what is called "script mode" (as in Think Python). Script mode simply Reads and Evaluates, there is not the Print-Loop part. A REPL is also called "interactive mode".
One could say that a REPL is very useful for prototyping and testing things out, but script mode is more useful for automation.
What you need to see the output would be like
print(the_line("just a boy"))
for line number 9.

How to print one character at a time in python within an input command?

So I know how to print one character at a time and the basic code I have for that is:
import time
import sys
def delay_print(s):
for c in s:
sys.stdout.write(c)
sys.stdout.flush()
time.sleep(0.2)
delay_print("hello world")
But I'm making a game and I'm using delay_print for all of my code and need a way to run it within user inputs without getting this result (there is no error but I don't really want a random "None" there).
GetUp=input (delay_print("\nGET UP? Y/N: "))
And when run it displays:
GET UP? Y/N: NoneN
Which isn't exactly what I want.
So what I need is for someone to tell me how to use delay_print without the "None" appearing. Other than that it runs correctly.
Just brake it into two lines and leave input() without a prompt:
delay_print("\nGET UP? Y/N: ")
GetUp = input()
That way, your print will behave the way you want it and the input will read the user input unobstructed.
Do not complicate your life when you don't have to ;)
If you insist on doing it in a single line you have to modify the definition of delay_print by adding a return '' statement. That way, instead of the default None it will return and empty string instead.
Note however, that GetUp=input(delay_print("\nGET UP? Y/N: ")) is not a very clean coding style. In my opinion that is.
You can return "" from delay_print, so input(delay_print("whatever")) will print slowly, then print an empty input prompt at the end of the line, which seems to be what you want.
The current behavior happens because delay_print returns None, and that is printed by input as a prompt.
See built-in function input:
If the prompt argument is present, it is written to standard output without a trailing newline.
You gave an argument (delay_print("\nGET UP? Y/N: ")) to it (as prompt). So, the interpreter first evaluates the argument. At this time, the program does the write, flush and sleep. Then it returns None (implied when running to the end of a function). That was then provided as the prompt of input().
Your code works like this one:
temp = delay_print("\nGET UP? Y/N: ")
# assert temp is None
GetUp = input(temp)
# Same as input(None)
So, that is the mistake.
The correct should be:
delay_print("\nGET UP? Y/N: ")
GetUp = input()
The None appeared because delay_print was returning no values.
import time
import sys
def delay_print(s):
for c in s:
if c:
sys.stdout.write(c)
sys.stdout.flush()
time.sleep(0.50)
return ''
#delay_print("hello world")
GetUp=input(delay_print("\nGET UP? Y/N: "))

Python game; Why can't I re-call my input and if/else function?

I'm still kind of learning Python, but my friend who has programmed in Python before says this should work fine, but it wont?
All code before this was the beginning story for this basic "escape the room" game I'm making. The code up until here works, (basic print functions describing the game).
I give the player the scenario that they're in a room and they can do one of two things:
def intro_room_input():
intro_action = input("What would you like to do? (Please enter either: 1 or 2) ")
return intro_action;
These two functions are for when they choose 1 or 2, the next if/elif function runs these functions
If they choose 1:
def intro_room_result1():
print(
"""
(Story stuff for the result of option 1. Not important to the code)
""")
return;
This function will play out if they choose 2
def intro_room_result2():
print(
"""
(Story stuff for the result of option 2. Not important to the code)
""")
return;
This will be the function for taking the player's input and continuing the story from there.
def intro_action_if(string):
if string == "1":
intro_room_result1()
elif string == "2":
intro_room_result2()
else:
print("I'm sorry, that wasn't one of the options that was available..."+'\n'+
"For this action, the options must be either '1' or '2'"+'\n'+
"Let me ask again...")
intro_room_input()
intro_action_if(string)
return;
that last intro_room_input runs fine, it re-runs the previous input, but when you actually enter 1 or 2, it doesn't do anything with them. It doesn't want to re-run the if/elif/else function to give the results.
finally I have a main that runs everything:
def main():
string = intro_room_input()
intro_action_if(string)
return;
main()
Please help, I have no idea what's wrong with this code!?
The problem is in your intro_action_if(). When you are calling the function to get values again, you forgot to change the string value.
ie,
#intro_room_input() #wrong
string = intro_room_input() #right
intro_action_if(string)
As you can see, even though in your code you asked for the user input and returned it, you forgot to reassign string with the returned value. Hence it kept the same input you had given previously and passed that old value to intro_action_if().

Indention Errors on Python IDLE

I'm just following the basic's of python and have been using IDLE as I find it handy to experiment scripts in real-time.
While I can run this script with no issues as a file I just cannot include the last print statement in IDLE!. I have tried an indentation, 4 spaces, no indentation's. Please explain what I'm doing wrong.
while True:
print ('Who are you?')
name = input()
if name != 'Joe':
continue
print('Hello, Joe. What is the password? (It is a fish.)')
password = input()
if password == 'swordfish':
break
print('value')
SyntaxError: invalid syntax
You can type one statement at a time. The while loop considered one with the loop itself, and since the loop is a code block everything in it is okay.
The print at the end however is a new command. You have to run the while loop first and type the print after in the interpreter.
You can't paste more than one statement at a time into IDLE. The problem has nothing to do with indentation. The while loop constitutes one compound statement and the final print another.
The following also has issues when you try to paste at once into IDLE:
print('A')
print('B')
The fact that this has a problem shows even more clearly that the issue ins't one of indentation.
You have an undentation error in line 10, then you need just to add an espace
while True:
print ('Who are you?')
name = input()
if name != 'Joe':
continue
print('Hello, Joe. What is the password? (It is a fish.)')
password = input()
if password == 'swordfish':
break
print('value')
As others have kindly pointed out python IDLE only allows one block of code to be executed at a time. In this instance the while loop is a 'block'. The last print statement is outside this block thus it cannot be executed.

Adding a while loop to my code to either re-run the program or terminate based on user input [Python 2.7]

I'm currently in the process of trying to add a while loop to my code that is shown below. The theory behind what I'm attempting to do is as follows:
As you can see at the very bottom of my code, I confirm the user's reservation and ask if he/she would like to create another. If the user enters 'yes", I would like the program to re-run. If no, then the program should terminate. I'm aware the best way to accomplish this is using a while loop, but I'm having a little difficulty executing this as my textbook is a little confusing on the subject.
I know it's supposed to look something like this (or something along the lines of it):
while True:
expression
break
Though I can't seem to get it to compile. Any suggestions? Below is my code:
user_continue = str(raw_input("Your reservation was submitted successfully. Would you like to do another?"))
if user_continue != 'yes':
print('Thank you for flying with Ramirez Airlines!')
Here's a simple example that shows how to use a while loop:
import time
while True:
print time.ctime()
print 'Doing stuff...'
response = raw_input('Would you like to do another? ')
if response != 'yes':
break
print 'Terminating'
Note that the code inside the while loop must be indented, unlike the code in your first code block. Indentation is very important in Python. Please always ensure that code in your questions (and answers) here is properly indented.
FWIW, the raw_input() input function returns a string, so str(raw_input()) is unnecessary clutter.
The end of your code should look something like:
user_continue = raw_input("Your reservation was submitted successfully. Would you like to do another?")
if user_continue != 'yes':
break
print('Thank you for flying with Ramirez Airlines!')
...
Your print statements are a bit funny. Since you're using Python 2.7 you don't need to do
print ('The total amount for your seats is: $'),user_people * 5180
you can just do
print 'The total amount for your seats is: $', user_people * 5180
or if you wish to use Python 3 style, put everything you're printing inside the parentheses, like this:
print ('The total amount for your seats is: $', user_people * 5180)
However, the output will look a bit messy since there will be a space between the $ and the amount. Please read the python docs to learn how to fix that.
...
Also, you have import time inside your loop. Don't do that. Generally, import statements should be at the top of your script before any other executable code.

Categories