You can use triple quotes to avoid any problem with nested single quotes:
subprocess.Popen('''echo "var1+'hello!'+var2"''', shell=True)
If you want to use the same triple quotes as the separator and inside the string, you need to avoid the quotes in the string:
'''some\'\'\'triple quotes\'\'\'''' -> "some'''triple quotes'''"
Alternatively, you can rely on the interpreter to concatenate consecutive string literals and use different quotes for different parts of the string:
subprocess.Popen('echo "var1+' "'hello!'" '+var2"', shell=True)
Note that this way you can even mix raw strings with jagged strings:
In [17]: print('non\traw' r'\traw' 'non\traw') non raw\trawnon raw
source share