Simple Morse Code Converter (Python)
As already mentioned in the comments, I don't think there's a strictly better way to create the morse code mapping. There is however a lot we can do to make this code more concise and more pythonic. This looks like Java code that was directly translated into Python and doesn't utilise some of Python's key features.

Morse Code dict
See the comments on your question: We don't need function createDict, which should be called create_dict (PEP 8), we only need a top-level variable:
CHAR_TO_MORSE = {'A': '.-',
                 ...
                 '0': '-----'}


Never iterate over indices in python
In Python this pattern is generally not recommended:
i = 0
while (i &lt; len(words)):
    print(words[i])

You almost never need to iterate over and access elements by their indices. Instead you should directly iterate over the elements of the iterable:
for word in words:
    print(word)

If you do need the index as well you can use built-in enumerate:
for index, word in enumerate(words):
    print(f&quot;{index}: {word}&quot;)

words is not a descriptive variable name for a string. If I iterate over a variable named words, I expect to receive words, not single characters. I'd change it to text or message and then change the loop to:
for char in text:
    ...

This makes it immediately clear what is happening.

Exception handling
Do not use bare except. Doing so can make it harder to interrupt programs and it can disguise other problems, since it catches all errors, not just the ones you're expecting. Instead you should only catch KeyError, since that's the only error you're explicitly handling.

words[i] != &quot; &quot;
You perform this check in every loop iteration, although it's not really a special case. This basically only translates &quot; &quot; to &quot;/&quot;, the rest of the logic is the same. So you can simply add it to your char to morse mapping:
CHAR_TO_MORSE = {'A': '.-',
                 ...
                 '0': '-----',
                 ' ': '/'}


Calling main()
For most use cases, you should wrap a call to main() from within the script in a if __name__ == “__main__”: condition.
if __name__ == &quot;__main__&quot;:
    main()

What does if name == “main”: do?

Complete code
I also applied .upper() directly to the return value of input(...) and moved the Exception clause into the loop to allow for a better error statement to the user.
CHAR_TO_MORSE = {'A': '.-',
                 ...
                 '0': '-----',
                 ' ': '/'}


def main():
    print(&quot;This program translates words to morse code&quot;, end=&quot;\n\n&quot;)

    text = input(&quot;Enter a word or phrase to be encoded: &quot;).upper()

    for char in text:
        try:
            print(CHAR_TO_MORSE[char], end=&quot; &quot;)
        except KeyError:
            print(f&quot;\nInvalid character found: '{char}' - refer to morse code alphabet&quot;)
            break


if __name__ == &quot;__main__&quot;:
    main()


join and list comprehensions / generator expressions
If you're not set on printing the morse code up until the invalid character, this is a perfect use case for join together with a list comprehension:
try:
    print(&quot; &quot;.join(CHAR_TO_MORSE[char] for char in text))
except KeyError:
    print(f&quot;\nInvalid character found - refer to morse code alphabet&quot;)

What we're using here is actually not a list comprehension, but a generator expression. If you're interested you can read more about Generator Expressions vs List Comprehensions.