def run(self, cmd, stdin=None, marshal_output=True, **kwargs):
        records = []
        args = [self._executable, "-u", self._user, "-p", self._port]
        if self._client:
            args += ["-c", str(self._client)]
        if marshal_output:
            args.append('-G')
        if isinstance(cmd, six.string_types):
            raise ValueError('String commands are not supported, please use a list')
        args += cmd
        command = ' '.join(args)
        startupinfo = None
        if os.name == 'nt':
            startupinfo = subprocess.STARTUPINFO()
            startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
        proc = subprocess.Popen(
            args,
            stdin=subprocess.PIPE,
            stdout=subprocess.PIPE,
            stderr=subprocess.PIPE,
            startupinfo=startupinfo,
            **kwargs
        )
        if stdin:
            proc.stdin.write(six.b(stdin))
        if marshal_output:
            try:
                while True:
                    record = marshal.load(proc.stdout)
                    if record.get(b'code', '') == b'error' and record[b'severity'] >= self._level:
                        proc.stdin.close()
                        proc.stdout.close()
                        raise errors.CommandError(record[b'data'], record, command)
                    if isinstance(record, dict):
                        if six.PY2:
                            records.append(record)
                        else:
                            records.append({str(k, 'utf8'): str(v) if isinstance(v, int) else str(v, 'utf8', errors='ignore') for k, v in record.items()})
            except EOFError:
                pass
            stdout, stderr = proc.communicate()
        else:
            records, stderr = proc.communicate()
        if stderr:
            raise errors.CommandError(stderr, command)
        return records