Skip to content

Commit 441a8bb

Browse files
committed
CHANGE: changed default value of line_terminator to os.linesep
* re-defined testcases that suits conversations in PR pandas-dev#21406 * changed default value of line_terminator to os.linesep * changed API document of DataFrame.to_csv * changed "newline" value of "open()" from '\n' to '' * Updated whatsnew document related pages: * Issue pandas-dev#20353 * PR pandas-dev#21406
1 parent 48f5685 commit 441a8bb

File tree

6 files changed

+58
-17
lines changed

6 files changed

+58
-17
lines changed

doc/source/whatsnew/v0.24.0.txt

+2-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@ Other Enhancements
2323

2424
Backwards incompatible API changes
2525
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
26-
26+
- When file path is given by string format in :func:`DataFrame.to_csv`, it disables universal newline support.
27+
- Instead, default value of `line_terminator` in :func:`DataFrame.to_csv` has changed from `'\n'` to `os.linesep`(:issue:`20353`)
2728
.. _whatsnew_0240.api.datetimelike:
2829

2930
Datetimelike API Changes

pandas/core/frame.py

+4-3
Original file line numberDiff line numberDiff line change
@@ -1653,7 +1653,7 @@ def to_panel(self):
16531653
def to_csv(self, path_or_buf=None, sep=",", na_rep='', float_format=None,
16541654
columns=None, header=True, index=True, index_label=None,
16551655
mode='w', encoding=None, compression=None, quoting=None,
1656-
quotechar='"', line_terminator='\n', chunksize=None,
1656+
quotechar='"', line_terminator=None, chunksize=None,
16571657
tupleize_cols=None, date_format=None, doublequote=True,
16581658
escapechar=None, decimal='.'):
16591659
r"""Write DataFrame to a comma-separated values (csv) file
@@ -1690,9 +1690,10 @@ def to_csv(self, path_or_buf=None, sep=",", na_rep='', float_format=None,
16901690
compression : string, optional
16911691
A string representing the compression to use in the output file.
16921692
Allowed values are 'gzip', 'bz2', 'zip', 'xz'.
1693-
line_terminator : string, default ``'\n'``
1693+
line_terminator : string, optional
16941694
The newline character or character sequence to use in the output
1695-
file
1695+
file. Defaults to `os.linesep`, which depends on the OS in which
1696+
this method is called ('\n' for linux, '\r\n' for Windows, i.e.).
16961697
quoting : optional constant from csv module
16971698
defaults to csv.QUOTE_MINIMAL. If you have set a `float_format`
16981699
then floats are converted to strings and thus csv.QUOTE_NONNUMERIC

pandas/io/common.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -399,10 +399,10 @@ def _get_handle(path_or_buf, mode, encoding=None, compression=None,
399399
f = open(path_or_buf, mode)
400400
elif encoding:
401401
# Python 3 and encoding
402-
f = open(path_or_buf, mode, encoding=encoding, newline='\n')
402+
f = open(path_or_buf, mode, encoding=encoding, newline='')
403403
elif is_text:
404404
# Python 3 and no explicit encoding
405-
f = open(path_or_buf, mode, errors='replace', newline='\n')
405+
f = open(path_or_buf, mode, errors='replace', newline='')
406406
else:
407407
# Python 3 and binary mode
408408
f = open(path_or_buf, mode)

pandas/io/formats/csvs.py

+3
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
import csv as csvlib
99
import numpy as np
10+
import os
1011

1112
from pandas.core.dtypes.missing import notna
1213
from pandas.core.dtypes.inference import is_file_like
@@ -61,6 +62,8 @@ def __init__(self, obj, path_or_buf=None, sep=",", na_rep='',
6162
self.doublequote = doublequote
6263
self.escapechar = escapechar
6364

65+
if line_terminator is None:
66+
line_terminator = os.linesep
6467
self.line_terminator = line_terminator
6568

6669
self.date_format = date_format

pandas/tests/frame/test_to_csv.py

+10-1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
import csv
66
import pytest
7+
import os
78

89
from numpy import nan
910
import numpy as np
@@ -882,12 +883,20 @@ def test_to_csv_line_terminators(self):
882883
with open(path, mode='rb') as f:
883884
assert f.read() == expected
884885

885-
df.to_csv(path) # The default line terminator remains \n
886+
df.to_csv(path, line_terminator='\n')
886887

887888
expected = (b',A,B\none,1,4\ntwo,2,5\nthree,3,6\n')
888889
with open(path, mode='rb') as f:
889890
assert f.read() == expected
890891

892+
os_linesep = os.linesep.encode('utf-8')
893+
df.to_csv(path) # The default line terminator=os.linesep(PR 21406)
894+
895+
expected = (b',A,B' + os_linesep + b'one,1,4' + os_linesep +
896+
b'two,2,5' + os_linesep + b'three,3,6' + os_linesep)
897+
with open(path, mode='rb') as f:
898+
assert f.read() == expected
899+
891900
def test_to_csv_from_csv_categorical(self):
892901

893902
# CSV with categoricals should result in the same output as when one

pandas/tests/io/formats/test_to_csv.py

+37-10
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# -*- coding: utf-8 -*-
22

33
import sys
4+
import os
45
import numpy as np
56
import pandas as pd
67
import pytest
@@ -294,20 +295,33 @@ def test_to_csv_string_with_lf(self):
294295
}
295296
df = pd.DataFrame(data)
296297

298+
os_linesep = os.linesep.encode('utf-8')
299+
297300
with tm.ensure_clean('lf_test.csv') as path:
298-
expected_bin = (
301+
expected_noarg = (
302+
b'int,str_lf' + os_linesep +
303+
b'1,abc' + os_linesep +
304+
b'2,"d\nef"' + os_linesep +
305+
b'3,"g\nh\n\ni"' + os_linesep
306+
)
307+
308+
df.to_csv(path, index=False)
309+
with open(path, 'rb') as f:
310+
assert f.read() == expected_noarg
311+
312+
expected_lf = (
299313
b'int,str_lf\n'
300314
b'1,abc\n'
301315
b'2,"d\nef"\n'
302316
b'3,"g\nh\n\ni"\n'
303317
)
304318

305-
df.to_csv(path, index=False)
319+
df.to_csv(path, line_terminator='\n', index=False)
306320
with open(path, 'rb') as f:
307-
assert f.read() == expected_bin
321+
assert f.read() == expected_lf
308322

309323
# 'line_terminator' should not change inner element
310-
expected_bin = (
324+
expected_crlf = (
311325
b'int,str_lf\r\n'
312326
b'1,abc\r\n'
313327
b'2,"d\nef"\r\n'
@@ -316,7 +330,7 @@ def test_to_csv_string_with_lf(self):
316330

317331
df.to_csv(path, line_terminator='\r\n', index=False)
318332
with open(path, 'rb') as f:
319-
assert f.read() == expected_bin
333+
assert f.read() == expected_crlf
320334

321335
def test_to_csv_string_with_crlf(self):
322336
# GH 20353
@@ -326,19 +340,32 @@ def test_to_csv_string_with_crlf(self):
326340
}
327341
df = pd.DataFrame(data)
328342

343+
os_linesep = os.linesep.encode('utf-8')
344+
329345
with tm.ensure_clean('crlf_test.csv') as path:
330-
expected_bin = (
346+
expected_noarg = (
347+
b'int,str_crlf' + os_linesep +
348+
b'1,abc' + os_linesep +
349+
b'2,"d\r\nef"' + os_linesep +
350+
b'3,"g\r\nh\r\n\r\ni"' + os_linesep
351+
)
352+
353+
df.to_csv(path, index=False)
354+
with open(path, 'rb') as f:
355+
assert f.read() == expected_noarg
356+
357+
expected_lf = (
331358
b'int,str_crlf\n'
332359
b'1,abc\n'
333360
b'2,"d\r\nef"\n'
334361
b'3,"g\r\nh\r\n\r\ni"\n'
335362
)
336363

337-
df.to_csv(path, index=False)
364+
df.to_csv(path, line_terminator='\n', index=False)
338365
with open(path, 'rb') as f:
339-
assert f.read() == expected_bin
366+
assert f.read() == expected_lf
340367

341-
expected_bin = (
368+
expected_crlf = (
342369
b'int,str_crlf\r\n'
343370
b'1,abc\r\n'
344371
b'2,"d\r\nef"\r\n'
@@ -347,4 +374,4 @@ def test_to_csv_string_with_crlf(self):
347374

348375
df.to_csv(path, line_terminator='\r\n', index=False)
349376
with open(path, 'rb') as f:
350-
assert f.read() == expected_bin
377+
assert f.read() == expected_crlf

0 commit comments

Comments
 (0)