@@ -125,16 +125,40 @@ def __init__(self, obj, path_or_buf=None, sep=",", na_rep='',
125125
126126 def save (self ):
127127 # create the writer & save
128- encoding = self .encoding
129- if encoding is None :
130- encoding = 'ascii' if compat .PY2 else 'utf-8'
131-
132- f , handles = _get_handle (
133- path_or_buf = self .path_or_buf ,
134- mode = self .mode ,
135- encoding = encoding ,
136- compression = self .compression ,
137- )
128+ if self .encoding is None :
129+ if compat .PY2 :
130+ encoding = 'ascii'
131+ else :
132+ encoding = 'utf-8'
133+ else :
134+ encoding = self .encoding
135+
136+ # GH 21227 internal compression is not used when file-like passed.
137+ if self .compression and hasattr (self .path_or_buf , 'write' ):
138+ msg = ("compression has no effect when passing file-like "
139+ "object as input." )
140+ warnings .warn (msg , RuntimeWarning , stacklevel = 2 )
141+
142+ # when zip compression is called.
143+ is_zip = isinstance (self .path_or_buf , ZipFile ) or (
144+ not hasattr (self .path_or_buf , 'write' )
145+ and self .compression == 'zip' )
146+
147+ if is_zip :
148+ # zipfile doesn't support writing string to archive. uses string
149+ # buffer to receive csv writing and dump into zip compression
150+ # file handle. GH 21241, 21118
151+ f = StringIO ()
152+ close = False
153+ elif hasattr (self .path_or_buf , 'write' ):
154+ f = self .path_or_buf
155+ close = False
156+ else :
157+ f , handles = _get_handle (self .path_or_buf , self .mode ,
158+ encoding = encoding ,
159+ compression = self .compression )
160+ close = True
161+
138162 try :
139163 writer_kwargs = dict (lineterminator = self .line_terminator ,
140164 delimiter = self .sep , quoting = self .quoting ,
@@ -150,8 +174,21 @@ def save(self):
150174 self ._save ()
151175
152176 finally :
153- for handle in handles :
154- handle .close ()
177+ if is_zip :
178+ # GH 17778 handles zip compression separately.
179+ buf = f .getvalue ()
180+ if hasattr (self .path_or_buf , 'write' ):
181+ self .path_or_buf .write (buf )
182+ else :
183+ f , handles = _get_handle (self .path_or_buf , self .mode ,
184+ encoding = encoding ,
185+ compression = self .compression )
186+ f .write (buf )
187+ close = True
188+ if close :
189+ f .close ()
190+ for _fh in handles :
191+ _fh .close ()
155192
156193 def _save_header (self ):
157194
0 commit comments