Skip to content

API: add reads_json, reads_msgpack, reads_csv, reads_pickle as convience functions which accept a string #5957

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
wants to merge 1 commit into from
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
8 changes: 4 additions & 4 deletions pandas/io/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@
Data IO api
"""

from pandas.io.parsers import read_csv, read_table, read_fwf
from pandas.io.parsers import read_csv, reads_csv, read_table, read_fwf
from pandas.io.clipboard import read_clipboard
from pandas.io.excel import ExcelFile, ExcelWriter, read_excel
from pandas.io.pytables import HDFStore, Term, get_store, read_hdf
from pandas.io.json import read_json
from pandas.io.json import read_json, reads_json
from pandas.io.html import read_html
from pandas.io.sql import read_sql
from pandas.io.stata import read_stata
from pandas.io.pickle import read_pickle, to_pickle
from pandas.io.packers import read_msgpack, to_msgpack
from pandas.io.pickle import read_pickle, reads_pickle, to_pickle
from pandas.io.packers import read_msgpack, reads_msgpack, to_msgpack
from pandas.io.gbq import read_gbq
33 changes: 32 additions & 1 deletion pandas/io/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

from pandas.compat import StringIO
from pandas import compat

from functools import wraps

if compat.PY3:
from urllib.request import urlopen, pathname2url
Expand Down Expand Up @@ -45,6 +45,37 @@ class PerformanceWarning(Warning):
class DtypeWarning(Warning):
pass

def _create_string_file_reader(func):
"""
create and return a new function that takes string input and
passed to a file-like reader function,
e.g. read_json

Parameters
----------
func : the function with a file-like interface

Returns
-------
new function that transform input to file-like
"""

@wraps(func)
def f(path_or_buf, *args, **kwargs):
if not hasattr(path_or_buf,'read'):
if isinstance(path_or_buf, compat.string_types):
path_or_buf = StringIO(path_or_buf)
elif isinstance(path_or_buf, compat.binary_type):
path_or_buf = compat.BytesIO(path_or_buf)
try:
return func(path_or_buf, *args, **kwargs)
finally:
if not ('iterator' in kwargs or 'chunksize' in kwargs):
path_or_buf.close()

return func(path_or_buf, *args, **kwargs)

return f

def _is_url(url):
"""Check to see if a URL has a valid protocol.
Expand Down
30 changes: 10 additions & 20 deletions pandas/io/json.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
from pandas.compat import long, u
from pandas import compat, isnull
from pandas import Series, DataFrame, to_datetime
from pandas.io.common import get_filepath_or_buffer
from pandas.io.common import get_filepath_or_buffer, _create_string_file_reader
import pandas.core.common as com

loads = _json.loads
Expand Down Expand Up @@ -109,7 +109,7 @@ def read_json(path_or_buf=None, orient=None, typ='frame', dtype=True,

Parameters
----------
filepath_or_buffer : a valid JSON string or file-like
path_or_buffer : a valid file-like
The string could be a URL. Valid URL schemes include http, ftp, s3, and
file. For file URLs, a host is expected. For instance, a local file
could be ``file://localhost/path/to/table.json``
Expand Down Expand Up @@ -171,25 +171,14 @@ def read_json(path_or_buf=None, orient=None, typ='frame', dtype=True,
result : Series or DataFrame
"""

filepath_or_buffer, _ = get_filepath_or_buffer(path_or_buf)
if isinstance(filepath_or_buffer, compat.string_types):
try:
exists = os.path.exists(filepath_or_buffer)

# if the filepath is too long will raise here
# 5874
except (TypeError,ValueError):
exists = False

if exists:
with open(filepath_or_buffer, 'r') as fh:
json = fh.read()
else:
json = filepath_or_buffer
elif hasattr(filepath_or_buffer, 'read'):
json = filepath_or_buffer.read()
path_or_buffer, _ = get_filepath_or_buffer(path_or_buf)
if isinstance(path_or_buffer, compat.string_types):
with open(path_or_buffer, 'r') as fh:
json = fh.read()
elif hasattr(path_or_buffer, 'read'):
json = path_or_buffer.read()
else:
json = filepath_or_buffer
raise ValueError("path_or_buffer must be a file or file-like buffer")

obj = None
if typ == 'frame':
Expand All @@ -206,6 +195,7 @@ def read_json(path_or_buf=None, orient=None, typ='frame', dtype=True,

return obj

reads_json = _create_string_file_reader(read_json)

class Parser(object):

Expand Down
29 changes: 9 additions & 20 deletions pandas/io/packers.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@
from pandas.sparse.array import BlockIndex, IntIndex
from pandas.core.generic import NDFrame
from pandas.core.common import needs_i8_conversion
from pandas.io.common import get_filepath_or_buffer
from pandas.io.common import get_filepath_or_buffer, _create_string_file_reader
from pandas.core.internals import BlockManager, make_block
import pandas.core.internals as internals

Expand Down Expand Up @@ -124,7 +124,7 @@ def read_msgpack(path_or_buf, iterator=False, **kwargs):

Parameters
----------
path_or_buf : string File path, BytesIO like or string
path_or_buf : string File path or buffer
iterator : boolean, if True, return an iterator to the unpacker
(default is False)

Expand All @@ -146,26 +146,15 @@ def read(fh):
# see if we have an actual file
if isinstance(path_or_buf, compat.string_types):

try:
exists = os.path.exists(path_or_buf)
except (TypeError,ValueError):
exists = False

if exists:
with open(path_or_buf, 'rb') as fh:
return read(fh)

# treat as a string-like
if not hasattr(path_or_buf, 'read'):

try:
fh = compat.BytesIO(path_or_buf)
with open(path_or_buf, 'rb') as fh:
return read(fh)
finally:
fh.close()

# a buffer like
return read(path_or_buf)
elif hasattr(path_or_buf, 'read'):
return read(path_or_buf)
else:
raise ValueError("path_or_buffer must be a file or file-like buffer")

reads_msgpack = _create_string_file_reader(read_msgpack)

dtype_dict = {21: np.dtype('M8[ns]'),
u('datetime64[ns]'): np.dtype('M8[ns]'),
Expand Down
3 changes: 2 additions & 1 deletion pandas/io/parsers.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
import pandas.core.common as com
from pandas.core.config import get_option
from pandas.io.date_converters import generic_parser
from pandas.io.common import get_filepath_or_buffer
from pandas.io.common import get_filepath_or_buffer, _create_string_file_reader

from pandas.util.decorators import Appender

Expand Down Expand Up @@ -417,6 +417,7 @@ def parser_f(filepath_or_buffer,

read_csv = _make_parser_function('read_csv', sep=',')
read_csv = Appender(_read_csv_doc)(read_csv)
reads_csv = _create_string_file_reader(read_csv)

read_table = _make_parser_function('read_table', sep='\t')
read_table = Appender(_read_table_doc)(read_table)
Expand Down
4 changes: 3 additions & 1 deletion pandas/io/pickle.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from pandas.compat import cPickle as pkl, pickle_compat as pc, PY3

from pandas.io.common import _create_string_file_reader

def to_pickle(obj, path):
"""
Expand Down Expand Up @@ -51,3 +51,5 @@ def try_read(path, encoding=None):
if PY3:
return try_read(path, encoding='latin1')
raise

reads_pickle= _create_string_file_reader(read_pickle)
Loading