Skip to content

Fix 25648 improve read csv stacktrace on bad argument #33023

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions doc/source/whatsnew/v1.1.0.rst
Original file line number Diff line number Diff line change
Expand Up @@ -355,6 +355,7 @@ I/O
- Bug in :meth:`read_csv` was causing a segfault when there were blank lines between the header and data rows (:issue:`28071`)
- Bug in :meth:`read_csv` was raising a misleading exception on a permissions issue (:issue:`23784`)
- Bug in :meth:`read_csv` was raising an ``IndexError`` when header=None and 2 extra data columns
- `TypeError` exceptions raised by :meth:`read_csv` and :meth:`read_table` were showing as ``parser_f`` when an unexpected keyword argument was passed (:issue:`25648`)


Plotting
Expand Down
33 changes: 19 additions & 14 deletions pandas/io/parsers.py
Original file line number Diff line number Diff line change
Expand Up @@ -528,9 +528,14 @@ def _read(filepath_or_buffer: FilePathOrBuffer, kwds):


def _make_parser_function(name, default_sep=","):
def parser_f(
filepath_or_buffer: FilePathOrBuffer,
sep=default_sep,
exec(
f"""
from pandas._typing import FilePathOrBuffer
import csv

def {name}(
filepath_or_buffer : FilePathOrBuffer,
sep="{default_sep}",
delimiter=None,
# Column and Index Locations and Names
header="infer",
Expand Down Expand Up @@ -583,7 +588,7 @@ def parser_f(
warn_bad_lines=True,
# Internal
delim_whitespace=False,
low_memory=_c_parser_defaults["low_memory"],
low_memory={_c_parser_defaults["low_memory"]},
memory_map=False,
float_precision=None,
):
Expand All @@ -601,7 +606,7 @@ def parser_f(
# the comparison to dialect values by checking if default values
# for BOTH "delimiter" and "sep" were provided.
if dialect is not None:
sep_override = delimiter is None and sep == default_sep
sep_override = delimiter is None and sep == "{default_sep}"
kwds = dict(sep_override=sep_override)
else:
kwds = dict()
Expand All @@ -610,7 +615,7 @@ def parser_f(
if delimiter is None:
delimiter = sep

if delim_whitespace and delimiter != default_sep:
if delim_whitespace and delimiter != "{default_sep}":
raise ValueError(
"Specified a delimiter with both sep and "
"delim_whitespace=True; you can only specify one."
Expand Down Expand Up @@ -674,29 +679,29 @@ def parser_f(
)

return _read(filepath_or_buffer, kwds)

parser_f.__name__ = name

return parser_f
""",
globals(),
)


read_csv = _make_parser_function("read_csv", default_sep=",")
_make_parser_function("read_csv", default_sep=",")
read_csv = Appender(
_doc_read_csv_and_table.format(
func_name="read_csv",
summary="Read a comma-separated values (csv) file into DataFrame.",
_default_sep="','",
)
)(read_csv)
)(read_csv) # noqa F821


read_table = _make_parser_function("read_table", default_sep="\t")
_make_parser_function("read_table", default_sep="\t")
read_table = Appender(
_doc_read_csv_and_table.format(
func_name="read_table",
summary="Read general delimited file into DataFrame.",
_default_sep=r"'\\t' (tab-stop)",
)
)(read_table)
)(read_table) # noqa F821


def read_fwf(
Expand Down
8 changes: 8 additions & 0 deletions pandas/tests/io/parser/test_common.py
Original file line number Diff line number Diff line change
Expand Up @@ -2126,3 +2126,11 @@ def test_no_header_two_extra_columns(all_parsers):
parser = all_parsers
df = parser.read_csv(stream, header=None, names=column_names, index_col=False)
tm.assert_frame_equal(df, ref)


def test_unexpected_keyword_parameter_exception(all_parsers):
# GH 25648
parser = all_parsers
msg = "read_csv\\(\\) got an unexpected keyword argument 'foo'"
with pytest.raises(TypeError, match=msg):
parser.read_csv("foo.csv", foo=1)