используйте информацию type () для приведения значений, хранящихся в виде строк - PullRequest
4 голосов
/ 13 сентября 2011

В моем приложении я сгенерировал несколько значений (три столбца, типа int, str и datetime, см. Пример ниже), и эти значения хранятся в плоском файле в виде строк, разделенных запятыми. Кроме того, я храню файл, содержащий тип значений (см. Ниже). Теперь, как я могу использовать эту информацию для преобразования моих значений из плоского файла в правильный тип данных в Python? Возможно ли это или мне нужно заняться чем-то другим?

Файл данных:

#id,value,date
1,a,2011-09-13 15:00:00
2,b,2011-09-13 15:10:00
3,c,2011-09-13 15:20:00
4,d,2011-09-13 15:30:00

Тип файла:

id,<type 'int'>
value,<type 'str'>
date,<type 'datetime.datetime'>

Ответы [ 7 ]

2 голосов
/ 13 сентября 2011

Ваш файл типов может быть проще:

id=int
value=str
date=datetime.datetime

Тогда в вашей основной программе вы можете

import datetime

def convert_datetime(text):
    return datetime.datetime.strptime(text, "%Y-%m-%d %H:%M:%S")

data_types = {'int':int, 'str':str, 'datetime.datetime':convert_datetime}
fields = {}

for line in open('example_types.txt').readlines():
    key, val = line.strip().split('=')
    fields[key] = val

data_file = open('actual_data.txt')
field_info = data_file.readline().strip('#\n ').split(',')
values = [] #store it all here for now

for line in data_file.readlines():
    row = []
    for i, element in enumerate(line.strip().split(',')):
        element_type = fields[field_info[i]] # will get 'int', 'str', or 'datetime'
        convert = data_types[element_type]
        row.append(convert(element))
    values.append(row)

# to show it working...
for row in values:
    print row
2 голосов
/ 13 сентября 2011

Как я понимаю, вы уже проанализировали файл, теперь вам просто нужно получить правильный тип. Допустим, id_, type_ и value - это три строки, которые содержат значения в файле. (Примечание: type_ должно содержать 'int' & mdash; например & mdash; не '<type 'int'>'.

def convert(value, type_):
    import importlib
    try:
        # Check if it's a builtin type
        module = importlib.import_module('__builtin__')
        cls = getattr(module, type_)
    except AttributeError:
        # if not, separate module and class
        module, type_ = type_.rsplit(".", 1)
        module = importlib.import_module(module)
        cls = getattr(module, type_)
    return cls(value)

Тогда вы можете использовать его как ..:

value = convert("5", "int")

К сожалению, для datetime это не работает, так как его нельзя просто инициализировать его строковым представлением.

1 голос
/ 13 сентября 2011

Мне пришлось столкнуться с подобной ситуацией в недавней программе, которая должна была конвертировать много полей.Я использовал список кортежей, где одним из элементов кортежей была используемая функция преобразования.Иногда это было int или float;иногда это было просто lambda;а иногда это было имя функции, определенной в другом месте.

1 голос
/ 13 сентября 2011

Выполните следующие действия:

  1. Читайте файл построчно, для каждой строки выполните следующие шаги
  2. Разделить линию, используя split() с , в качестве разделителя.
  3. Приведите первый элемент списка (из шага 2) как int. Сохранить второй элемент как строку. Разобрать третье значение (e.g. using slices) и сделать datetime объект таким же.
0 голосов
/ 13 сентября 2011

Возможно, вы захотите взглянуть на модуль xlrd. Если вы можете загрузить свои данные в Excel и он знает, какой тип связан с каждым столбцом, xlrd сообщит вам тип при чтении файла Excel. Конечно, если данные передаются вам в виде csv, тогда кто-то должен будет зайти в файл excel и вручную изменить типы столбцов.

Не уверен, что это приведет вас туда, куда вы хотите пойти, но это может помочь

0 голосов
/ 13 сентября 2011

Во-первых, вы не можете написать «универсальное» или «умное» преобразование, которое магически обрабатывает что-либо.

Во-вторых, попытка суммировать преобразование строки в данные во что-либо, кроме кода, кажется, никогда не работает хорошо. Поэтому вместо того, чтобы писать строку с именем преобразования, просто запишите преобразование.

Наконец, пытаться написать файл конфигурации на доменном языке глупо. Просто напишите код Python. Это не намного сложнее, чем пытаться разобрать какой-то файл конфигурации.

Возможно или мне нужно заняться чем-нибудь другим?

Не тратьте время на попытки создать "файл типа", который не просто Python. Это не помогает Проще написать преобразование как функцию Python. Вы можете импортировать эту функцию, как если бы это был ваш «файл типа».

import datetime

def convert( row ):
   return dict(
       id= int(row['id']),
       value= str(row['value']),
       date= datetime.datetime.strptime(row['date],"%Y-%m-%d %H:%M:%S"),
   )

Это все, что у вас есть в вашем "файле типа"

Теперь вы можете читать (и обрабатывать) ваш ввод следующим образом.

 from type_file import convert
 import csv

 with open( "date", "rb" ) as source:
     rdr= csv.DictReader( source )
     for row in rdr:
         useful_row= convert( row )

во многих случаях я не знаю количество столбцов или тип данных до выполнения

Это означает, что вы обречены.

У вас должно быть фактическое определение содержимого файла, или вы не можете выполнять какую-либо обработку.

"id","value","other value"
1,23507,3

Вы не знаете, должно ли "23507" быть целым числом, строкой, почтовым индексом или с плавающей запятой (без учета периода), продолжительностью (в днях или секундах) или какой-либо другой более сложной вещью , Вы не можете надеяться, и вы не можете догадаться.

После получения определения вам нужно написать явную функцию преобразования на основе фактического определения.

После написания преобразования вам нужно (а) проверить преобразование с помощью простого модульного теста и (б) проверить данные, чтобы убедиться, что они действительно преобразуются.

Затем вы можете обработать файл.

0 голосов
/ 13 сентября 2011

Вместо того, чтобы иметь отдельный файл типа, возьмите свой список кортежей (id, value, date) и просто pickle it.

Или вам придется решить проблемухранения ваших строковых преобразователей в виде текста (в вашем «типовом» файле), что может быть забавной проблемой, но если вы просто пытаетесь что-то сделать, используйте pickle или cPickle

...