DEPR: pd.read_table
State: closed

`pd.read_table` is deprecated and replaced by `pd.read_csv`.

- [x] closes #21948
- [x] tests added / passed
- [x] passes `git diff upstream/master -u -- "*.py" | flake8 --diff`
- [x] whatsnew entry


Labels:
name: IO Data
description: IO issues that don't fit into a more specific label
name: Deprecate
description: Functionality to remove in pandas

Comments:
Initial comments:

- Needs test(s)
- Since we are replacing `read_table` with `read_csv` and a sep of `\t`you should reroute the call to `read_table` to reflect this
 - Needs whatsnew note
Hello @dahlbaek! Thanks for updating the PR.





















Cheers ! There are no PEP8 issues in this Pull Request. :beers: 

##### Comment last updated on August 02, 2018 at 10:48 Hours UTC
Added a whatsnew note.

I'm not sure what to do about tests. `pd.read_csv` has been around for as long as I've been using pandas, so I would suspect that tests are already plentiful.

I changed the warning message so that it will reflect whether or not the user is supplying a value to `sep`. The result is now similar to what I proposed in #21948 but without the decorator, as suggested by @gfyoung. Result:

```pycon
In [1]: import pandas as pd

In [2]: df = pd.DataFrame({"a": [1], "b": [2]})
   ...: df.to_csv("test.csv", sep="\t")

In [3]: pd.read_table("test.csv", index_col=0)
/home/dahlbaek/virtualenvs/pandas-dev/bin/ipython:1: FutureWarning: read_table is deprecated, use read_csv with sep='\t' instead.
  #!/home/dahlbaek/virtualenvs/pandas-dev/bin/python
Out[3]: 
   a  b
0  1  2

In [4]: pd.read_table("test.csv", "\t", index_col=0)
/home/dahlbaek/virtualenvs/pandas-dev/bin/ipython:1: FutureWarning: read_table is deprecated, use read_csv instead.
  #!/home/dahlbaek/virtualenvs/pandas-dev/bin/python
Out[4]: 
   a  b
0  1  2

In [5]: pd.read_table("test.csv", sep="\t", index_col=0)
/home/dahlbaek/virtualenvs/pandas-dev/bin/ipython:1: FutureWarning: read_table is deprecated, use read_csv instead.
  #!/home/dahlbaek/virtualenvs/pandas-dev/bin/python
Out[5]: 
   a  b
0  1  2

In [6]: pd.read_table("test.csv", delimiter="\t", index_col=0)
/home/dahlbaek/virtualenvs/pandas-dev/bin/ipython:1: FutureWarning: read_table is deprecated, use read_csv instead.
  #!/home/dahlbaek/virtualenvs/pandas-dev/bin/python
Out[6]: 
   a  b
0  1  2

In [7]: pd.read_csv("test.csv", "\t", index_col=0)
Out[7]: 
   a  b
0  1  2

In [8]: pd.read_csv("test.csv", sep="\t", index_col=0)
Out[8]: 
   a  b
0  1  2

In [9]: pd.read_csv("test.csv", delimiter="\t", index_col=0)
Out[9]: 
   a  b
0  1  2
```
We definitely have tests for `read_table` in the codebase.  Modify them to assert that a warning is produced.
@gfyoung I modified the tests, but am unsure how to proceed with the `stacklevel` parameter. It seems to me `stacklevel=2` gives the correct behaviour. Since the warning message is hardcoded into the function body, this will give the user the file/line of the call to the function producing the warning message, so the user can make suitable adjustments. Example:
```sh
$ cat test_warn.py 
import pandas as pd

pd.read_table("test.csv", index_col=0)
$ python test_warn.py 
test_warn.py:3: FutureWarning: read_table is deprecated, use read_csv with sep='\t' instead.
  pd.read_table("test.csv", index_col=0)
```
This is exactly the behaviour I would want as a user. Nevertheless, `pandas.util.testing.assert_produces_warning` complains that the stacklevel is not set correctly, which causes failed tests.

Please Advise.
@dahlbaek : Pass in `check_stacklevel=False` in your tests.
> @dahlbaek : Pass in check_stacklevel=False in your tests.

Perfect, that's what I figured.
# [Codecov](https://codecov.io/gh/pandas-dev/pandas/pull/21954?src=pr&el=h1) Report
> Merging [#21954](https://codecov.io/gh/pandas-dev/pandas/pull/21954?src=pr&el=desc) into [master](https://codecov.io/gh/pandas-dev/pandas/commit/647f3f091eedd715b7966829a36ef345de4d7a4d?src=pr&el=desc) will **increase** coverage by `<.01%`.
> The diff coverage is `100%`.

[![Impacted file tree graph](https://codecov.io/gh/pandas-dev/pandas/pull/21954/graphs/tree.svg?width=650&height=150&src=pr&token=eZ4WkYLtcO)](https://codecov.io/gh/pandas-dev/pandas/pull/21954?src=pr&el=tree)

```diff
@@            Coverage Diff             @@
##           master   #21954      +/-   ##
==========================================
+ Coverage   92.06%   92.06%   +<.01%     
==========================================
  Files         170      170              
  Lines       50720    50728       +8     
==========================================
+ Hits        46694    46702       +8     
  Misses       4026     4026
```

| Flag | Coverage Δ | |
|---|---|---|
| #multiple | `90.47% <100%> (ø)` | :arrow_up: |
| #single | `42.29% <53.33%> (-0.01%)` | :arrow_down: |

| [Impacted Files](https://codecov.io/gh/pandas-dev/pandas/pull/21954?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [pandas/io/clipboards.py](https://codecov.io/gh/pandas-dev/pandas/pull/21954/diff?src=pr&el=tree#diff-cGFuZGFzL2lvL2NsaXBib2FyZHMucHk=) | `100% <ø> (ø)` | :arrow_up: |
| [pandas/core/frame.py](https://codecov.io/gh/pandas-dev/pandas/pull/21954/diff?src=pr&el=tree#diff-cGFuZGFzL2NvcmUvZnJhbWUucHk=) | `97.26% <100%> (ø)` | :arrow_up: |
| [pandas/io/parsers.py](https://codecov.io/gh/pandas-dev/pandas/pull/21954/diff?src=pr&el=tree#diff-cGFuZGFzL2lvL3BhcnNlcnMucHk=) | `95.48% <100%> (+0.02%)` | :arrow_up: |

------

[Continue to review full report at Codecov](https://codecov.io/gh/pandas-dev/pandas/pull/21954?src=pr&el=continue).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/pandas-dev/pandas/pull/21954?src=pr&el=footer). Last update [647f3f0...9002460](https://codecov.io/gh/pandas-dev/pandas/pull/21954?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).

@WillAyd @gfyoung: Does this solution seem reasonable?
I wonder if it would be better to get rid of the function factory `_make_parser_function` altogether and define `read_csv` and `read_table` separately. It would cause some code duplication, but the code would be easier to read. Also, in the future I would like to propose aligning parameter names of `read_csv` and `to_csv`, and perhaps propose changes to the current `sep`/`delimiter` situation (#7662), but there is no reason those changes should affect `read_table`.
Not sure I completely follow your logic there but it doesn't really seem worth the effort to do, especially since you are deprecating `read_table` here
Well, right now `read_table` and `read_csv` are both produced by `_make_parser_function`, so my solution basically has

```python
if False:
    # deprecate read_table
```
inside `read_csv`, which seems suboptimal. But I guess you're right that it isn't worth it. In that case, I guess the PR is ready.
there is also a check for using pd.read_table in the top-level api that I am not sure is affected but pls check (pandas/tests/api/test_api.py)
> there is also a check for using pd.read_table in the top-level api that I am not sure is affected but pls check (pandas/tests/api/test_api.py)

I think that test checks the pandas namespace, which I suppose should not change until `pandas.read_table` is actually removed. So no change required at this point in time, unless I am mistaken.
@gfyoung if you have any comments
> some comments. can you run the test suite and make sure you are catching all deprecation warnings for read_table.

I'm not seeing any `FutureWarning`s from `read_table`, but I am getting the following failed test:

```
(pandas-dev) $ pwd
/home/dahlbaek/git/pandas/pandas/tests
(pandas-dev) $ pytest test_errors.py
=============================== test session starts ===============================
platform linux -- Python 3.6.6, pytest-3.6.3, py-1.5.4, pluggy-0.6.0
rootdir: /home/dahlbaek/git/pandas, inifile: setup.cfg
plugins: xdist-1.22.2, forked-0.2, cov-2.5.1
collected 12 items                                                                

test_errors.py ..........F.                                                 [100%]

==================================== FAILURES =====================================
________________________________ test_error_rename ________________________________

    def test_error_rename():
        # see gh-12665
        from pandas.errors import ParserError
        from pandas.io.common import CParserError
    
        try:
            raise CParserError()
        except ParserError:
            pass
    
        try:
            raise ParserError()
        except CParserError:
            pass
    
        with catch_warnings(record=True):
            try:
>               raise ParserError()
E               pandas.errors.ParserError

test_errors.py:52: ParserError
======================= 1 failed, 11 passed in 0.07 seconds =======================
(pandas-dev) $ 
```

Not sure exactly what is happening here…
@dahlbaek : That's an odd test failure.  Seems to be fine on Travis though.  Also, the test logs don't seem to have any deprecation warnings related to `read_table` AFAICT.
@dahlbaek we don't usually run *from* the test dir itself, rather from the base dir e.t.
``pytest path/to/test``. running from the test dir might not find the fixtures. 
@jorisvandenbossche @TomAugspurger any objections?
@jreback After recreating my virtual environment from scratch, I still get that failed test, even on master, when running from the base dir. Not sure what the cause is, but as pointed out by @gfyoung it seems to be a local problem on my machine.
@dahlbaek see my comments above. The tests are not designed to be run from subdirs, nor are they on our CI. pytest can't find things.
@jreback I think I am now running the test the way proposed in the [docs](https://pandas.pydata.org/pandas-docs/stable/contributing.html#running-the-test-suite), right? I still get the failure (even on master). In any case, this seems unrelated to the current PR. I suppose it is a local phenomenon that I will have to figure out myself…

```
(pandas-dev) $ pytest pandas/tests/test_errors.py -k test_error_rename
=============================== test session starts ===============================
platform linux -- Python 3.6.6, pytest-3.6.3, py-1.5.4, pluggy-0.6.0
rootdir: /home/dahlbaek/git/pandas, inifile: setup.cfg
plugins: xdist-1.22.3, forked-0.2, cov-2.5.1
collected 12 items / 11 deselected                                                

pandas/tests/test_errors.py F                                               [100%]

==================================== FAILURES =====================================
________________________________ test_error_rename ________________________________

    def test_error_rename():
        # see gh-12665
        from pandas.errors import ParserError
        from pandas.io.common import CParserError
    
        try:
            raise CParserError()
        except ParserError:
            pass
    
        try:
            raise ParserError()
        except CParserError:
            pass
    
        with catch_warnings(record=True):
            try:
>               raise ParserError()
E               pandas.errors.ParserError

pandas/tests/test_errors.py:52: ParserError
===================== 1 failed, 11 deselected in 0.06 seconds =====================
(pandas-dev) $ 
```
@dahlbaek hmm that looks like a real error
@jreback I'll try to look into it when I have time and make a separate issue.
@jreback I re-cloned the repo and installed a fresh python3.7 environment. I don't know what was causing the problem, but now it is gone.
@TomAugspurger if you have any issues here
@dahlbaek : This looks good to me, though if you could fix the merge conflicts, that would be good.
@gfyoung Done.
Pushed a doc formatting fix.

Thanks @dahlbaek!