0
\$\begingroup\$

I have a function where I am comparing an error string returned from a web service to several lists of known strings, and then based on which list the error is a member of, returning from the function a more 'user-friendly' error to display.

I am hoping someone could offer some tips on making it shorter and more efficient. I think I'm missing some obvious shortcuts, but I am not sure what.

def interpret_error(error):
    display_error_1 = 'User error 1'

    display_error_2 = 'User error 2'

    display_error_3 = 'User error 3'


    error_list_1= ["Failure: 'mean_va' is not in list",
                   "Failure: No JSON object could be decoded",
                   "Failure: Expecting ':' delimiter: line 1 column 14410098 (char 14410097)",
                   "Failure: cannot concatenate 'str' and 'ContentDecodingError' objects",
                   "Failure: Unknown error",
                   "Failure: Error returned by EPA WATERS web service: No Results Returned"]

    error_list_2 = ["Failure: Error returned by EPA WATERS web service: Flowline comid 4505568 at measure 79.99388 not found in NHDPlus stream network",
                    "Failure: Error returned by EPA WATERS web service: No Catchments match navigation results"]

    error_list_3 = ["Failure: Error returned by EPA WATERS web service: Start permid must have a hydroseq greater than the hydroseq for stop permid",
                    "Failure: Error returned by EPA WATERS web service: Start measure must be greater than stop measure when navigating a single reach"]

    match1 = 0.0
    match2 = 0.0
    match3 = 0.0
    temp_match = 0.0

    for internal_error in error_list_1:
        temp_match = fuzz.token_set_ratio(error,internal_error)
        match1 = max(temp_match, match1)

    temp_match = 0.0

    for internal_error in error_list_2:
        temp_match = fuzz.token_set_ratio(error,internal_error)
        match2 = max(temp_match, match2)

    temp_match = 0.0

    for internal_error in error_list_3:
        temp_match = fuzz.token_set_ratio(error,internal_error)
        match3 = max(temp_match, match3)

    if match1 > match2 and match1 > match3:
        return display_error_1
    elif match2 > match1 and match2 > match3:
        return display_error_2
    elif match3 > match1 and match3 > match2:
        return display_error_3
    else:
        return "Error of unknown cause"
\$\endgroup\$
1
\$\begingroup\$

The inner for loops can be made easier:

match1 = max(fuzz.token_set_ratio(error, internal_error) for internal_error in error_list1)

And similar for match2 and match3.

However, the real complixity in your implementation lies in the determining of the error message to show.

I would suggest building a dictionary mapping the display error to internal errors:

def interpret_error(error):
    error_mapping = {
        "User error 1": [
            "Failure: 'mean_va' is not in list",
            "Failure: No JSON object could be decoded",
            "Failure: Expecting ':' delimiter: line 1 column 14410098 (char 14410097)",
            "Failure: cannot concatenate 'str' and 'ContentDecodingError' objects",
            "Failure: Unknown error",
            "Failure: Error returned by EPA WATERS web service: No Results Returned",
        ],
        "User error 2": [
            "Failure: Error returned by EPA WATERS web service: Flowline comid 4505568 at measure 79.99388 not found in NHDPlus stream network",
            "Failure: Error returned by EPA WATERS web service: No Catchments match navigation results",
        ],
        "User error 3": [
            "Failure: Error returned by EPA WATERS web service: Start permid must have a hydroseq greater than the hydroseq for stop permid",
            "Failure: Error returned by EPA WATERS web service: Start measure must be greater than stop measure when navigating a single reach",
        ],
    }

    display_error = None
    score = 0.0
    for message, internal_errors in error_mapping.items():
        tmp = max(fuzz.token_set_ratio(error, internal_error) for internal_error in internal_errors)

        # This matches better than any earlier internal_error.
        if tmp >= score:
            score = tmp
            display_error = message

    return display_error

Ideally: move the mapping to a separate .py file, or some form of config file (.json, .yaml or even .xml), or the database.

\$\endgroup\$
  • \$\begingroup\$ very insightful implementation - I'm not sure if I'm willing to implement the second part of it though - it's a trade off there of fewer lines, but much harder to understand code. If I were a better programmer, I would probably take both your suggestions - but my own limitations and those for whom I'm building this script, might relegate me to leaving out that part of your suggestion for now. \$\endgroup\$ – traggatmot Apr 10 '16 at 22:12

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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