2
\$\begingroup\$

I a creating a program to parse a simple language in a text file and delegate those actions to python-turtle. You pass the path to the file(s) you want to be parsed into the program, and a turtle window is shown.

This is my code:

import sys

import turtle
import time

t = turtle.Turtle()

functions = {
    "F": t.forward,
    "B": t.backward,

    "R": t.right,
    "L": t.left,
    "H": t.seth,

    "C": t.circle,

    "U": t.penup,
    "D": t.pendown,

    "W": time.sleep,

    "T": t.shape,
    "V": t.speed,

    "P": t.pensize,
    "S": t.shapesize,

    "O": turtle.done
}


def prep_args(args):
    output = []
    for arg in args:
        try:
            output.append(int(arg))
        except:
            output.append(arg)

    return output


def parse_line(line):
    if line.strip() == "":
        return

    action = line.strip()[0]

    assert action in functions, f"Unknown Action: {action}"

    args = line.strip().split(" ")[1:]
    args = prep_args(args)

    functions[action](*args)


def parse_file(path):
    with open(path, "r") as f:
        for line in f.readlines():
            parse_line(line)


for argv in sys.argv[1:]:
    parse_file(argv)

Example input file:

F 100
R 90
F 50
C 20
T square
W 5

V 0
S 5
U
F 50
D
C 30 180 5
H 90
F 3

S 1
O

I would be grateful for any help to improve this program.

\$\endgroup\$

1 Answer 1

3
\$\begingroup\$

The code is pretty small and straight-forward, I mainly see minor improvements. I find it somewhat strange that parse_file() is what calls on the main function, and how you deal with args in the files is not super easy to follow or debug; you can't really validate your arguments the way that you have set this up. It would be helpful to add an example file with this type of code.

It's a bit unnecessary to call on str.split() 3 times in parse_line()

def parse_line(line):
    line = line.strip()
    action = line[0]

    assert action in functions, f"Unknown Action: {action}"

    args = line.split(" ")[1:]
    args = prep_args(args)

    functions[action](*args)

And instead of asserting and raising an AssertionError with a custom message to the user you could just catch the KeyError and print

def parse_line(line):
    line = line.strip()
    action = line[0]
    args = line.split(" ")[1:]
    args = prep_args(args)

    try:
        functions[action](*args)
    except KeyError:
        print(f"Unknown action: {action}")
\$\endgroup\$
1
  • \$\begingroup\$ Note that OP explicitly allows empty input lines, and action = line[0] will IndexError on them. \$\endgroup\$
    – J_H
    Commented Apr 21, 2023 at 17:57

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.