Would that work for you? Please note that since the order of elements in the dictionary is arbitrary, you cannot guarantee which keys will end up being inserted into the output dictionary.
dict_out = {}
processed = set()
for k1, v1 in dict_in.items():
if k1 not in processed:
processed.add(k1)
vo = v1
for k2, v2 in dict_in.items():
if k2 not in processed and set(v1) & set(v2):
vo = sorted(list(set(vo + v2)))
processed.add(k2)
dict_out[k1] = vo
This for:
dict_in = {'key1': ['1', '2', '3'], 'key2': ['3', '4', '5'], 'key3': ['6', '7', '8']}
gives:
{'key1': {'1', '2', '3', '4', '5'}, 'key3': ['6', '7', '8']}
And for:
dict_in = {'key1': ['1', '2', '3'], 'key2': ['3', '4', '5'],
'key3': ['6', '7', '8'], 'key4': ['7', '9']}
gives:
{'key1': {'1', '2', '3', '4', '5'}, 'key3': {'6', '7', '8', '9'}}
And finally, for:
dict_in = {'key1': ['1', '2', '3'], 'key2': ['3', '4', '5'],
'key3': ['6', '7', '8'], 'key4': ['5', '6', '7']}
it gives:
{'key1': {'1', '2', '3', '4', '5'}, 'key3': {'5', '6', '7', '8'}}
EDIT
OP requested that even outcomes of merges should be merged with each other. To achieve that, we can wrap the code above in a loop like this:
d = dict_in
processed = set([None])
while processed:
dict_out = {}
processed = set()
for k1, v1 in d.items():
if k1 not in processed:
vo = v1
for k2, v2 in d.items():
if k1 is not k2 and set(vo) & set(v2):
vo = sorted(list(set(vo + v2)))
processed.add(k2)
dict_out[k1] = vo
d = dict_out
Then, for:
dict_in = {'key1': ['1', '2', '3'], 'key2': ['3', '4', '5'],
'key3': ['6', '7', '8'], 'key4': ['5', '6', '7']}
we get:
{'key4': ['1', '2', '3', '4', '5', '6', '7', '8']}
and for:
dict_in = {'key1': ['1', '2', '3'], 'key2': ['3', '4', '5'],
'key3': ['4', '6', '7'], 'key4': ['8', '9']}
we get:
{'key1': ['1', '2', '3', '4', '5', '6', '7'], 'key4': ['8', '9']}