1#!/usr/bin/env python 2 3import io 4import itertools 5 6import six 7 8 9@classmethod 10def from_csv(cls, path, column_names=None, column_types=None, row_names=None, skip_lines=0, header=True, sniff_limit=0, 11 encoding='utf-8', row_limit=None, **kwargs): 12 """ 13 Create a new table from a CSV. 14 15 This method uses agate's builtin CSV reader, which supplies encoding 16 support for both Python 2 and Python 3. 17 18 :code:`kwargs` will be passed through to the CSV reader. 19 20 :param path: 21 Filepath or file-like object from which to read CSV data. If a file-like 22 object is specified, it must be seekable. If using Python 2, the file 23 should be opened in binary mode (`rb`). 24 :param column_names: 25 See :meth:`.Table.__init__`. 26 :param column_types: 27 See :meth:`.Table.__init__`. 28 :param row_names: 29 See :meth:`.Table.__init__`. 30 :param skip_lines: 31 The number of lines to skip from the top of the file. 32 :param header: 33 If :code:`True`, the first row of the CSV is assumed to contain column 34 names. If :code:`header` and :code:`column_names` are both specified 35 then a row will be skipped, but :code:`column_names` will be used. 36 :param sniff_limit: 37 Limit CSV dialect sniffing to the specified number of bytes. Set to 38 None to sniff the entire file. Defaults to 0 (no sniffing). 39 :param encoding: 40 Character encoding of the CSV file. Note: if passing in a file 41 handle it is assumed you have already opened it with the correct 42 encoding specified. 43 :param row_limit: 44 Limit how many rows of data will be read. 45 """ 46 from agate import csv 47 from agate.table import Table 48 49 close = False 50 51 try: 52 if hasattr(path, 'read'): 53 f = path 54 else: 55 if six.PY2: 56 f = open(path, 'Urb') 57 else: 58 f = io.open(path, encoding=encoding) 59 60 close = True 61 62 if isinstance(skip_lines, int): 63 while skip_lines > 0: 64 f.readline() 65 skip_lines -= 1 66 else: 67 raise ValueError('skip_lines argument must be an int') 68 69 contents = six.StringIO(f.read()) 70 71 if sniff_limit is None: 72 kwargs['dialect'] = csv.Sniffer().sniff(contents.getvalue()) 73 elif sniff_limit > 0: 74 kwargs['dialect'] = csv.Sniffer().sniff(contents.getvalue()[:sniff_limit]) 75 76 if six.PY2: 77 kwargs['encoding'] = encoding 78 79 reader = csv.reader(contents, header=header, **kwargs) 80 81 if header: 82 if column_names is None: 83 column_names = next(reader) 84 else: 85 next(reader) 86 87 if row_limit is None: 88 rows = tuple(reader) 89 else: 90 rows = tuple(itertools.islice(reader, row_limit)) 91 92 finally: 93 if close: 94 f.close() 95 96 return Table(rows, column_names, column_types, row_names=row_names) 97