First of all: you do not need shell=True. Use this instead:
subprocess.Popen(["rsync", "-apvr", "source", "destination", "--progress"], stdout=subprocess.PIPE)
Or, if you don't want to manually split the command line:
import shlex
subprocess.Popen(shlex.split("rsync -apvr source destination --progress"), stdout=subprocess.PIPE)
Second: communicate waits the end of the process. If you want to actually mix the output of the subprocess with the current process you can simply avoid specifying stdout=subprocess.PIPE, or maybe you could specify stdout=sys.stdout if you want to be explicit:
import sys
subprocess.Popen(["rsync", "-apvr", "source", "destination", "--progress"], stdout=sys.stdout)
this will print the output of rsync in the stdout of your process.
If you instead want to parse the output "in real time" you'll have to use stdout=subprocess.PIPE and read from Popen.stdout manually:
proc = subprocess.Popen(["rsync", "-apvr", "source", "destination", "--progress"], stdout=sys.stdout)
for line in proc.stdout:
do_something(line)
Depending on exactly what you want to do you may want to use the select module to get "non blocking reads" etc.