Coding With Basic Patterns
00:00
First, you can improve on the redundant case
clauses for exit and quit by using an OR pattern. Remove the case
clause for command.
00:07 Quit and add bar command. Quit to the command. Exit case.
00:14
Great. Looking better already. Now, for your REPL to be a proper REPL, you’ll want to be able to run code. You can use the built-in exec()
function.
00:24 It takes a string as an argument, reads it as Python code, and executes it. This lets you leverage Python’s parser for your REPL. Add a new case with a capture pattern to match the user’s input as a statement and run it.
00:41
Let’s see if this works. Open the REPL Python repl.py
, and you get an error. Syntax error: name capture statement makes remaining patterns unreachable.
00:54 This is because the pattern statement has no guard, no condition attached to it. Remember, capture patterns without a guard will match to anything because the wild card pattern is now unreachable, Python won’t even allow you to run this code.
01:07
And there’s another problem here. How do you know that what’s being passed to exec()
is syntactically valid Python? Well, since you’re here on Real Python, I know you’re a responsible Python developer, so you probably don’t want to run code that isn’t even correct.
01:21
Validating this input is exactly what a guard should do. So let’s add a guard pattern. First, add ast
, the abstract syntax tree module, to your list of imports.
01:33
Next, after the class command and before the main function, you can go ahead and write the valid()
function and that’s what you’ll use to validate the syntactical correctness of the code the user inputs. def valid(code):
and the try-except block: try: ast.parse(code)
.
01:52
This will run the code through the Python parser, and if there’s any syntax errors, this will create an error. If there are no errors, you’ll move to the next line and return True
.
02:03
If there is a syntax error, you catch it with the except block and return False
, meaning this function will only ever return True
or False
.
02:11
Now you can apply the guard to your case
clause, case statement
. If valid(statement)
, then execute the statement. Save the file and give it a try.
02:26
Python repl.py
seems to be working. Let’s see if I can access a variable that doesn’t exist. var
. Okay, perfect. A NameError
: name ‘var’ is not defined.
02:38 That seems like normal REPL behavior.
02:41
Now what if I try some kind of expression, like 5 + 5
?
02:47 Okay, nothing. So with a proper Python REPL, I would expect the evaluation of this expression to be reported to me, but so far we’ve only introduced handling of statements and not expressions.
Become a Member to join the conversation.