# Buggy code
def save(self) -> None:
    """
    Create the writer & save.
    """
    # GH21227 internal compression is not used when file-like passed.
    if self.compression and hasattr(self.path_or_buf, "write"):
        warnings.warn(
            "compression has no effect when passing file-like object as input.",
            RuntimeWarning,
            stacklevel=2,
        )

    # when zip compression is called.
    is_zip = isinstance(self.path_or_buf, ZipFile) or (
        not hasattr(self.path_or_buf, "write") and self.compression == "zip"
    )

    if is_zip:
        # zipfile doesn't support writing string to archive. uses string
        # buffer to receive csv writing and dump into zip compression
        # file handle. GH21241, GH21118
        f = StringIO()
        close = False
    elif hasattr(self.path_or_buf, "write"):
        f = self.path_or_buf
        close = False
    else:
        f, handles = get_handle(
            self.path_or_buf,
            self.mode,
            encoding=self.encoding,
            compression=dict(self.compression_args, method=self.compression),
        )
        close = True

    try:
        # Note: self.encoding is irrelevant here
        self.writer = csvlib.writer(
            f,
            lineterminator=self.line_terminator,
            delimiter=self.sep,
            quoting=self.quoting,
            doublequote=self.doublequote,
            escapechar=self.escapechar,
            quotechar=self.quotechar,
        )

        self._save()

    finally:
        if is_zip:
            # GH17778 handles zip compression separately.
            buf = f.getvalue()
            if hasattr(self.path_or_buf, "write"):
                self.path_or_buf.write(buf)
            else:
                compression = dict(self.compression_args, method=self.compression)

                f, handles = get_handle(
                    self.path_or_buf,
                    self.mode,
                    encoding=self.encoding,
                    compression=compression,
                )
                f.write(buf)
                close = True
        if close:
            f.close()
            for _fh in handles:
                _fh.close()
        elif self.should_close:
            f.close()


# Traceback (UnicodeEncodeError)
---------------------------------------------------------------------------
UnicodeEncodeError                        Traceback (most recent call last)
<ipython-input-50-769583baba38> in <module>()
4 srs = pd.Series()
5 srs.loc[ 0 ] = s
----> 6 srs.to_csv('testcase.csv')

/opt/conda/lib/python3.6/site-packages/pandas/core/series.py in to_csv(self, path, index, sep, na_rep, float_format, header, index_label, mode, encoding, compression, date_format, decimal)
3779                            index_label=index_label, mode=mode,
3780                            encoding=encoding, compression=compression,
-> 3781                            date_format=date_format, decimal=decimal)
3782         if path is None:
3783             return result

/opt/conda/lib/python3.6/site-packages/pandas/core/frame.py in to_csv(self, path_or_buf, sep, na_rep, float_format, columns, header, index, index_label, mode, encoding, compression, quoting, quotechar, line_terminator, chunksize, tupleize_cols, date_format, doublequote, escapechar, decimal)
1743                                  doublequote=doublequote,
1744                                  escapechar=escapechar, decimal=decimal)
-> 1745         formatter.save()
1746
1747         if path_or_buf is None:

/opt/conda/lib/python3.6/site-packages/pandas/io/formats/csvs.py in save(self)
169                 self.writer = UnicodeWriter(f, **writer_kwargs)
170
--> 171             self._save()
172
173         finally:

/opt/conda/lib/python3.6/site-packages/pandas/io/formats/csvs.py in _save(self)
284                 break
285
--> 286             self._save_chunk(start_i, end_i)
287
288     def _save_chunk(self, start_i, end_i):

/opt/conda/lib/python3.6/site-packages/pandas/io/formats/csvs.py in _save_chunk(self, start_i, end_i)
311
312         libwriters.write_csv_rows(self.data, ix, self.nlevels,
--> 313                                   self.cols, self.writer)

pandas/_libs/writers.pyx in pandas._libs.writers.write_csv_rows()

UnicodeEncodeError: 'utf-8' codec can't encode character '\ud800' in position 2: surrogates not allowed

# Fixed code
def save(self) -> None:
    """
    Create the writer & save.
    """
    # GH21227 internal compression is not used when file-like passed.
    if self.compression and hasattr(self.path_or_buf, "write"):
        warnings.warn(
            "compression has no effect when passing file-like object as input.",
            RuntimeWarning,
            stacklevel=2,
        )

    # when zip compression is called.
    is_zip = isinstance(self.path_or_buf, ZipFile) or (
        not hasattr(self.path_or_buf, "write") and self.compression == "zip"
    )

    if is_zip:
        # zipfile doesn't support writing string to archive. uses string
        # buffer to receive csv writing and dump into zip compression
        # file handle. GH21241, GH21118
        f = StringIO()
        close = False
    elif hasattr(self.path_or_buf, "write"):
        f = self.path_or_buf
        close = False
    else:
        f, handles = get_handle(
            self.path_or_buf,
            self.mode,
            encoding=self.encoding,
            errors=self.errors,
            compression=dict(self.compression_args, method=self.compression),
        )
        close = True

    try:
        # Note: self.encoding is irrelevant here
        self.writer = csvlib.writer(
            f,
            lineterminator=self.line_terminator,
            delimiter=self.sep,
            quoting=self.quoting,
            doublequote=self.doublequote,
            escapechar=self.escapechar,
            quotechar=self.quotechar,
        )

        self._save()

    finally:
        if is_zip:
            # GH17778 handles zip compression separately.
            buf = f.getvalue()
            if hasattr(self.path_or_buf, "write"):
                self.path_or_buf.write(buf)
            else:
                compression = dict(self.compression_args, method=self.compression)

                f, handles = get_handle(
                    self.path_or_buf,
                    self.mode,
                    encoding=self.encoding,
                    errors=self.errors,
                    compression=compression,
                )
                f.write(buf)
                close = True
        if close:
            f.close()
            for _fh in handles:
                _fh.close()
        elif self.should_close:
            f.close()