You need to exit the key using re.escape() :
somedata = re.sub(re.escape(key), 'newvalue', somedata)
otherwise, the content will be interpreted as a regular expression.
Here you do not use regular expressions at all, so you can simply use:
somedata = somedata.replace(key, 'newvalue')
If you want to replace only whole words (so that there are spaces or punctuation marks around them, at the beginning or end of the input line), you need some kind of boundary anchors, in which case it makes sense to use regular expressions. If all you have is alphanumeric words (plus underscores), \b will work:
somedata = re.sub(r'\b{}\b'.format(re.escape(key)), 'newvalue', somedata)
This puts \b before and after the line you want to replace, so baz in foo baz bar changed, but foo bazbaz bar is not.
For input, which includes non-alphanumeric words, you will need to match whitespace or start and concrete or end anchors with external and external images:
somedata = re.sub(r'(?:^|(?<=\s)){}(?:$|(?=\s))'.format(re.escape(key)), 'newvalue', somedata)
Here, the template (?:^|(?<=\s)) uses two anchors, a line-beginning binding and a look-behind statement to match places where there is either the beginning of a line or a space immediately to the left. Similarly (?:$|(?=\s) does the same for the other end, matching the end of the line or the position followed by a space.