If you use os.fork (with an os.setuid inside the child) you can collect the status using os.waitpid.
pid = os.fork()
if pid == 0:
    os.setgid(...)
    os.setgroups(...)
    os.setuid(...)
    # do something and collect the exit status... for example
    #
    # using os.system:
    #
    #      return_value = os.system(.....) // 256
    #
    # or using subprocess:
    #
    #      p = subprocess.Popen(....)
    #      out, err = p.communicate()
    #      return_value = p.returncode
    #
    # Or you can simply exec (this will not return to python but the 
    # exit status will still be visible in the parent).  Note there are 
    # several os.exec* calls, so choose the one which you want.
    #
    #      os.exec...
    #
    
    os._exit(return_value)
pid, status = os.waitpid(pid, 0)
print(f"Child exit code was {status // 256}")
Here I recently posted an answer to a related question which was not so much focused on the return value but does include some more details of the values that you might pass to the os.setuid etc calls.