2

I want to write a Python string that when executed does this:

if condition:
    consequence
else:
    alternative

So, I tried something like:

string = 'if condition: consequence; else: alternative;'

to be executed with:

>>> exec(string)
Traceback (most recent call last):
  File "<pyshell#5>", line 1, in <module>
    exec(string)
  File "<string>", line 1
    if condition: consequence; else: alternative;
                                  ^
SyntaxError: invalid syntax

But as you see, I get a syntax error. How should the string be formatted?

Thanks for the help!

PS: this question is not about how to evaluate or execute Python strings (See instead How do I execute a string containing Python code in Python?), but about the formatting required to execute an if..then..else clause.

Some context:

I am following the book "understanding computation" by Tom Stuart. Part of it is about understanding how programming languages work. So he gives example code for the implementation of a toy language 'SIMPLE'. He shows code in Ruby how to translate SIMPLE into Ruby code. However, I am trying to write this in Python, as that interests me more. The Ruby example is:

def to_ruby 
    "-> e { if (#{condition.to_ruby}).call(e)" + 
          " then (#{consequence.to_ruby}).call(e)" + 
          " else (#{alternative.to_ruby}).call(e)" + 
          " end }"
end
Community
  • 1
  • 1
tvo
  • 780
  • 7
  • 24
  • 2
    Are you sure that you need to use eval or exec? Using eval or exec is often a bad idea. What's the overall goal of this code? – Pikamander2 Dec 11 '15 at 01:50
  • I am following the book "understanding computation" by Tom Stuart. Part of it is about understanding how programming languages work. So he gives example code for the implementation of an toy language 'SIMPLE'. He shows code in Ruby how to translate SIMPLE into Ruby code. However, I am trying to write this in Python, as that interests me more. The Ruby example is: `def to_ruby "-> e { if (#{condition.to_ruby}).call(e)" + " then (#{consequence.to_ruby}).call(e)" + " else (#{alternative.to_ruby}).call(e)" + " end }" end` – tvo Dec 11 '15 at 01:54
  • I can't get the line breaks right in the previous comment. They're basically before each opening ". – tvo Dec 11 '15 at 02:00
  • you can use exec to execute a string but in this case you'd be better off using [conditional string formatting](https://stackoverflow.com/questions/9244909/python-conditional-string-formatting) – LinkBerest Dec 11 '15 at 02:05
  • 3
    Possible duplicate of [How do I execute a string containing Python code in Python?](http://stackoverflow.com/questions/701802/how-do-i-execute-a-string-containing-python-code-in-python) But remember use it **safely!** – Remi Guan Dec 11 '15 at 02:13
  • It is not a duplicate as I am aware of the tools 'exec' and 'eval', but had a specific question about formatting an if...then...else. Thx for the link though! – tvo Dec 11 '15 at 02:19
  • @tvo It *is* a duplicate. Do we need to have individual questions for how to handle a while loop in a string, an if statement in a string, a function in a string, a try/except block in a string, etc...? If you know how to handle those things normally, and you know how to execute code in strings with `exec` and `eval`, you should be generalize and come up with a solution to try. If you can't get it working, then you should include the code that you write, and exception/error messages, and descriptions of any other unexpected behavior you saw. – skrrgwasme Dec 11 '15 at 15:04
  • @skrrgwasme: it _is not_ a duplicate as the link to that page does not answer my question. No, we do not need a specific page for each different statement. But I had this question, and there was no answer available. So am I not allowed to ask it then? By the way, I _did_ include the code that I tried, which did not work: I got a syntax error. – tvo Dec 11 '15 at 15:10
  • Maybe I should have made the question more general: how to format a string such that it can be evaluated as a multi-line expression or statement? The answer by Tom Karzes is helpful, and I have compiled another answer myself with this input and what I found in the link by Kevin Guan. – tvo Dec 11 '15 at 15:11
  • If your code results in errors, you should include that in the question. I couldn't tell that you actually tried to write any code, because you just said "I'm looking for something like:". That doesn't tell me that you actually tried to run the code. If you've tried something, put the results in your question. Your suggested reworded version is better. The problem with the current question is that its solutions are a subset of the solutions in the other question; that's why it's a duplicate. If you narrow it down to specifically ask how to do it without using docstrings... – skrrgwasme Dec 11 '15 at 15:20
  • ...and remove your answer below, then you're left with a specific question that is asking about something that the other question doesn't address: using the newline characters in the command string. And you already have a good answer for it. If you add the traceback for your code to clearly show that you've tried to solve the problem on your own, you'll have a solid question, and I'll replace my downvote with an upvote, and retract my close vote. – skrrgwasme Dec 11 '15 at 15:21
  • In one of your first comments you wrote _"I am following the book ..."_. You should put that as part of your question so people can understand the context. – Bryan Oakley Dec 11 '15 at 15:27
  • @skrrgwasme: I did some edits to the question to show the traceback and make even more clear that this question is about the string formatting. I'm leaving my own answer, as I think both solution methods are valuable to the question. – tvo Dec 11 '15 at 15:43
  • @BryanOakley : I have put the context info in the question now. – tvo Dec 11 '15 at 15:47

2 Answers2

2

You can use exec to execute Python statements, including newlines:

>>> exec("if True:\n  print 'abc'\nelse:\n  print 'def'")
abc

If using Python 3, you would need parentheses for the prints:

>>> exec("if True:\n  print('abc')\nelse:\n  print('def')")
abc
Tom Karzes
  • 22,815
  • 2
  • 22
  • 41
2

Based on the input by Kevin Guan and Tom Karzes, I have found following alternative solution to the problem:

>>> exec("""
if True:
    print('abc')
else:
    print('def')
""")
abc

This format avoids the somewhat annoying \n symbols.

tvo
  • 780
  • 7
  • 24