Repository: pandas-dev/pandas

Issue:
lineterminator in to_csv doesn't work
```
In [3]: df = pd.DataFrame({'a': ['3.4', '34.400'], 'b': ['5,5', '10,200']})

In [4]: df
Out[4]:
        a       b
0     3.4     5,5
1  34.400  10,200

In [5]: df.to_csv(lineterminator='-')
Out[5]: ',a,b\n0,3.4,"5,5"\n1,34.400,"10,200"\n'
```

I would've expected

```
Out[5]: ',a,b-0,3.4,"5.5"-1,34.400,"10,200"-'
```



Discussion:
The argument in `DataFrame.to_csv()` is actually `line_terminator`, not `lineterminator`. A little confusing, since `csv.writer` uses the latter. The argument gets changed [here](https://github.com/pydata/pandas/blob/master/pandas/core/format.py#L1293).

Then I guess that confusion gets compounded by the fact that `DataFrame.to_csv()` accepts extra keyword args with a `**kwds` argument, but then doesn't seem to validate them. It only seems to use `engine` and `cols` from `**kwds`, so maybe the real issue here is that it should be warning if given unrecognized args?

definitely bad behaviour to accept invalid kwargs! if only engine and cols are used they should just be explicitly defined. 

@jreback : the `kwds` parameter is not used anymore in `to_csv` - can't we just remove it now (0.19.0)?

@gfyoung yep!


Resolving patch:
diff --git a/pandas/core/frame.py b/pandas/core/frame.py
--- a/pandas/core/frame.py
+++ b/pandas/core/frame.py
@@ -1305,7 +1305,7 @@ def to_csv(self, path_or_buf=None, sep=",", na_rep='', float_format=None,
                mode='w', encoding=None, compression=None, quoting=None,
                quotechar='"', line_terminator='\n', chunksize=None,
                tupleize_cols=False, date_format=None, doublequote=True,
-               escapechar=None, decimal='.', **kwds):
+               escapechar=None, decimal='.'):
         r"""Write DataFrame to a comma-separated values (csv) file
 
         Parameters
@@ -1332,8 +1332,6 @@ def to_csv(self, path_or_buf=None, sep=",", na_rep='', float_format=None,
             sequence should be given if the DataFrame uses MultiIndex.  If
             False do not print fields for index names. Use index_label=False
             for easier importing in R
-        nanRep : None
-            deprecated, use na_rep
         mode : str
             Python write mode, default 'w'
         encoding : string, optional
diff --git a/pandas/core/series.py b/pandas/core/series.py
--- a/pandas/core/series.py
+++ b/pandas/core/series.py
@@ -2534,8 +2534,8 @@ def from_csv(cls, path, sep=',', parse_dates=True, header=None,
         return result
 
     def to_csv(self, path, index=True, sep=",", na_rep='', float_format=None,
-               header=False, index_label=None, mode='w', nanRep=None,
-               encoding=None, date_format=None, decimal='.'):
+               header=False, index_label=None, mode='w', encoding=None,
+               date_format=None, decimal='.'):
         """
         Write Series to a comma-separated values (csv) file
 
@@ -2572,7 +2572,7 @@ def to_csv(self, path, index=True, sep=",", na_rep='', float_format=None,
         # result is only a string if no path provided, otherwise None
         result = df.to_csv(path, index=index, sep=sep, na_rep=na_rep,
                            float_format=float_format, header=header,
-                           index_label=index_label, mode=mode, nanRep=nanRep,
+                           index_label=index_label, mode=mode,
                            encoding=encoding, date_format=date_format,
                            decimal=decimal)
         if path is None:


Test patch:
diff --git a/pandas/tests/formats/test_format.py b/pandas/tests/formats/test_format.py
--- a/pandas/tests/formats/test_format.py
+++ b/pandas/tests/formats/test_format.py
@@ -3139,10 +3139,6 @@ def test_to_csv_quotechar(self):
             df.to_csv(path, quoting=1)  # 1=QUOTE_ALL
             with open(path, 'r') as f:
                 self.assertEqual(f.read(), expected)
-        with tm.ensure_clean('test.csv') as path:
-            df.to_csv(path, quoting=1, engine='python')
-            with open(path, 'r') as f:
-                self.assertEqual(f.read(), expected)
 
         expected = """\
 $$,$col$
@@ -3154,17 +3150,10 @@ def test_to_csv_quotechar(self):
             df.to_csv(path, quoting=1, quotechar="$")
             with open(path, 'r') as f:
                 self.assertEqual(f.read(), expected)
-        with tm.ensure_clean('test.csv') as path:
-            df.to_csv(path, quoting=1, quotechar="$", engine='python')
-            with open(path, 'r') as f:
-                self.assertEqual(f.read(), expected)
 
         with tm.ensure_clean('test.csv') as path:
             with tm.assertRaisesRegexp(TypeError, 'quotechar'):
                 df.to_csv(path, quoting=1, quotechar=None)
-        with tm.ensure_clean('test.csv') as path:
-            with tm.assertRaisesRegexp(TypeError, 'quotechar'):
-                df.to_csv(path, quoting=1, quotechar=None, engine='python')
 
     def test_to_csv_doublequote(self):
         df = DataFrame({'col': ['a"a', '"bb"']})
@@ -3178,18 +3167,11 @@ def test_to_csv_doublequote(self):
             df.to_csv(path, quoting=1, doublequote=True)  # QUOTE_ALL
             with open(path, 'r') as f:
                 self.assertEqual(f.read(), expected)
-        with tm.ensure_clean('test.csv') as path:
-            df.to_csv(path, quoting=1, doublequote=True, engine='python')
-            with open(path, 'r') as f:
-                self.assertEqual(f.read(), expected)
 
         from _csv import Error
         with tm.ensure_clean('test.csv') as path:
             with tm.assertRaisesRegexp(Error, 'escapechar'):
                 df.to_csv(path, doublequote=False)  # no escapechar set
-        with tm.ensure_clean('test.csv') as path:
-            with tm.assertRaisesRegexp(Error, 'escapechar'):
-                df.to_csv(path, doublequote=False, engine='python')
 
     def test_to_csv_escapechar(self):
         df = DataFrame({'col': ['a"a', '"bb"']})
@@ -3203,11 +3185,6 @@ def test_to_csv_escapechar(self):
             df.to_csv(path, quoting=1, doublequote=False, escapechar='\\')
             with open(path, 'r') as f:
                 self.assertEqual(f.read(), expected)
-        with tm.ensure_clean('test.csv') as path:
-            df.to_csv(path, quoting=1, doublequote=False, escapechar='\\',
-                      engine='python')
-            with open(path, 'r') as f:
-                self.assertEqual(f.read(), expected)
 
         df = DataFrame({'col': ['a,a', ',bb,']})
         expected = """\
@@ -3220,10 +3197,6 @@ def test_to_csv_escapechar(self):
             df.to_csv(path, quoting=3, escapechar='\\')  # QUOTE_NONE
             with open(path, 'r') as f:
                 self.assertEqual(f.read(), expected)
-        with tm.ensure_clean('test.csv') as path:
-            df.to_csv(path, quoting=3, escapechar='\\', engine='python')
-            with open(path, 'r') as f:
-                self.assertEqual(f.read(), expected)
 
     def test_csv_to_string(self):
         df = DataFrame({'col': [1, 2]})
diff --git a/pandas/tests/frame/test_to_csv.py b/pandas/tests/frame/test_to_csv.py
--- a/pandas/tests/frame/test_to_csv.py
+++ b/pandas/tests/frame/test_to_csv.py
@@ -896,7 +896,7 @@ def test_to_csv_path_is_none(self):
         # GH 8215
         # Make sure we return string for consistency with
         # Series.to_csv()
-        csv_str = self.frame.to_csv(path=None)
+        csv_str = self.frame.to_csv(path_or_buf=None)
         self.assertIsInstance(csv_str, str)
         recons = pd.read_csv(StringIO(csv_str), index_col=0)
         assert_frame_equal(self.frame, recons)