mesllo
mesllo

Reputation: 583

Is it wise to have if logic inside a python catch block?

Consider the following method that checks if a parameter contains a valid UUID string and generates a new one if it isn't and if the option is set:

def validate_uuid(val, generate):
    try:
        uuid.UUID(str(val))
        return val
    except ValueError:
        if generate:
            return str(uuid.uuid4())
        raise

I feel that for this particular use-case, having a small simple condition inside the catch block makes sense, however, I would like to understand if there's possibly a better way that adheres to pythonic principles.

Upvotes: 0

Views: 65

Answers (1)

T. Hall
T. Hall

Reputation: 301

Your function is not reuturning the processed uuid in the happy case:

def validate_uuid(val, generate):
    try:
        # uuid.UUID(str(val))
        # return val
        # ^^^^^^^^^^ this just returns the original value

        # try returning directly
        return uuid.UUID(str(val))

    except ValueError:
        if generate:
            return str(uuid.uuid4())
        raise

But to answer your question, in this small function its probably not too harmful, although it takes a bit of thinking to figure out whats going on. Theres also a naming issue; to a user (perhaps yourself, in the future), importing the validate_uuid function, you might be surprised that it can also generate different ones. The generate parameter does imply whats going on but will cause you to have to stop and think.

It's probably better practice to keep the logic outside of the error handling. One option could be to split the function in two and take the chance to give them more meaningful names:

def validate_uuid(val):
    return uuid.UUID(str(val))


def validate_or_create_uuid(val):
    try:
        return validate_uuid(val)
    except ValueError:
        return str(uuid.uuid4())

If you just want a function to raise an error if any string is not a correctly formed uuid then no need to return at all. Or you could use the try/except logic to return a boolean.

def raise_for_invalid_uuid(val):
    uuid.UUID(val)


def is_valid_uuid(val):
    try:
        uuid.UUID(str(val))
        return True
    except ValueError:
        return False

Upvotes: 3

Related Questions