Morse code encoder decoder I created this morse code encoder and decoder.

class DecodeError(BaseException):
    __module__ = Exception.__module__

class EncodeError(BaseException):
    __module__ = Exception.__module__


code_letter = {
    '.-': 'A', '-...': 'B', '-.-.': 'C', '-..': 'D', '.': 'E', '..-.': 'F', '--.': 'G',
    '....': 'H', '..': 'I', '.---': 'J', '-.-': 'K', '.-..': 'L', '--': 'M', '-.': 'N',
    '---': 'O', '.--.': 'P', '--.-': 'Q', '.-.': 'R', '...': 'S', '-': 'T', '..-': 'U',
    '...-': 'V', '.--': 'W', '-..-': 'X', '-.--': 'Y', '--..': 'Z',

    '.----': '1', '..---': '2', '...--': '3', '....-': '4', '.....': '5',
    '-....': '6', '--...': '7', '---..': '8', '----.': '9', '-----': '0',

    '--..--': ', ', '.-.-.-': '.', '..--..': '?', '-..-.': '/',
    '-....-': '-', '-.--.': '(', '-.--.-': ')', '/': ' '
}


letter_code = {value: key for key, value in zip(code_letter.keys(), code_letter.values())}


def morse_encode(string: str) -&gt; str:
    try:
        return ' '.join(letter_code[i.upper()] for i in string)
    except:
        raise EncodeError('Unknown value in string')


def morse_decode(string: str) -&gt; str:
    try:
        return ''.join(code_letter[i] for i in string.split())
    except:
        raise DecodeError('Unknown value in string')

if __name__ == '__main__':
    string = input()
    print(morse_encode(string))


Is it possible to make the code shorter while maintaining neatness?

Thanks!
Some suggestions:


I believe the idiomatic way to declare custom exceptions is to inherit from Exception rather than BaseException, and to just use the no-op pass as the class body. I've not seen the __module__ = Exception.__module__ pattern before, but if that does what it looks like (making the class effectively part of the exceptions module) that's probably going to be misleading. It's not a generic error, after all.
It might be faster to put both upper and lower case characters in the dict than to use upper(). You could test this with timeit.
If you're processing a big string of Morse code you might want to use an iterator. That way the string is processed one word at a time, rather than having to split the entire text into a list in memory before starting to output anything.
Rather than parsing input() I would expect this sort of script to either read standard input or to accept a list of file path arguments which would each be read and converted.
If the script also accepted --encode and --decode parameters (possibly with --encode as the default) it could easily be used to script a conversion of any text.