Есть ли способ найти и установить DataType из файла CSV, не указывая его заранее? - PullRequest
0 голосов
/ 13 июля 2020

Я заметил пример пользователя 647772 из Чтение данных из файла CSV ...

data = """True,foo,1,2.3,baz
False,bar,7,9.8,qux"""
reader = csv.reader(StringIO.StringIO(data), delimiter=",")
parsed = (({'True':True}.get(row[0], False),
       row[1],
       int(row[2]),
       float(row[3]),
       row[4])
      for row in reader)
 getBackData = list(parsed)

Я не смог найти много информации о библиотеке CSV Reader, связанной с кодом, написанным для "переменная. Я был бы очень признателен, если бы кто-нибудь мог указать мне правильную документацию на веб-сайте python.

Кроме того, мне интересно узнать, есть ли способ определить тип данных и установить значение переменной проанализирован (см. выше) во время выполнения. Итак, является ли следующая реализация «действительной», если я изменю приведенный выше код, например:

parsed = "((row[0], int(row[1]), int(row[2]), int(row[3]), row[4], row[5]) for row in rawReader)"

и

getBackData = list(eval((parsed)))

Или есть способ лучше?

1 Ответ

0 голосов
/ 13 июля 2020

Переменная parsed не является особенной для csv.reader (библиотеки CSV Reader нет, csv - это модуль в Python std lib). Это синтаксис Python generator expression. Хотя этот код работает , сжатие нескольких концепций в один оператор не всегда лучший вариант при попытке проиллюстрировать концепцию.

Более удобная для новичков форма этого кода может выглядеть так:

reader = csv.reader(StringIO.StringIO(data), delimiter=",")

# use a conventional for loop to build up the getBackData list
getBackData = []
for row in reader:
    converted_row = (
        row[0] == 'True',
        row[1],
        int(row[2]),
        float(row[3]),
        row[4],
        )
    getBackData.append(converted_row)

Еще чище было бы сделать sh все эти преобразователи в функцию convert_row, а затем создать getBackData с пониманием списка:

def convert_row(raw):
    return (
        raw[0] == 'True',
        raw[1],
        int(raw[2]),
        float(raw[3]),
        raw[4],
        )

reader = csv.reader(StringIO.StringIO(data), delimiter=",")
getBackData = [convert_row(row) for row in reader]

Затем вы можете изменить функцию convert_row, как вам нравится, но конструкция reader и getBackData останется прежней.

EDIT: получение типов (не очень хорошо протестировано, но это идея)

def try_bool(s):
    # will convert strings "True" and "False" to bools,
    # and raise an exception otherwise
    try:
        return {"True": True, "False": False}[s]
    except KeyError:
        raise ValueError("{!r} is not a valid bool".format(s))

def get_column_types(raw):
    types = []
    for col in raw:
        for test_type in (int, float, try_bool, str):
            try:
                test_type(col)
            except ValueError:
                # fail! not data of this type
                pass
            else:
                # it worked! add test_type to list of converters
                types.append(test_type)
                break
    return types

# read the first row and get the types of each column
first_row = next(csv.reader(input_file))
col_types = get_column_types(first_row)

# now create a list of new rows with converted data items
converted = []
for row in csv.reader(input_file):
    # use zip to walk list of converters and list of columns at the same time
    converted_row = [converter(raw_value)
                         for converter, raw_value in zip(col_types, row)]
    converted.append(converted_row)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...