Найти - Пользователи
Полная версия: Парсинг csv
Начало » Python для новичков » Парсинг csv
1 2 3
py.user.next
Я там поменял исходник, так как он не был доделан. Результат тот же, но теперь функции меньше связаны.
old_monty
Если кто не в курсе, то возможно будет полезно это небольшое замечание насчет модуля csv. Модуль csv (пока еще) не работает с файлами, в которых имеются символы Unicode.

Например, если файл myfile.xlsx, созданный в Excel, сохранен в формате csv, то код
import csv
with open('myfile.csv') as mf:
      mfreader = csv.reader(mf)
      print(list(mfreader))
будет работать с файлом myfile.csv, если в нем содержатся только английские (а не русские) буквы.

ПОПРАВКА: при указании кодировки работает и с русскими буквами (см. ниже)
py.user.next
old_monty
одуль csv (пока еще) не работает с файлами, в которых имеются символы Unicode.
Это не из-за модуля csv, а из-за того, что файл открыт без указания кодировки .
i.z
Хм.. Честное слово до последнего не спрашивал здесь помощи, думал справлюсь сам. Утром взял скрипт и визжа от радости начал разбираться, но, скрипт усиленно не хочет работать, после нескольких исправлений он выдает одну за другой ошибку. И сейчас я стою на ошибке
TypeError: ‘newline’ is an invalid keyword argument for this function

Код который я пробую запустить:
import csv
import xml.etree.ElementTree as ET
import lxml.html
 
def read_csv(fname):
    with open(fname, newline='') as f:
        f.readline()
        reader = csv.reader(f)
        for i in reader:
            yield i
 
def convert_csv_to_xml(csvstream, csvnums, xmlroot, xmlnode, xmlnames):
    out = '<?xml version="1.0"?>'
    doc = ET.Element(xmlroot)
    for i in csvstream:
        selected = select_fields(i, csvnums)
        section = make_xml_section(xmlnode, xmlnames, selected)
        node_clean_html(section[3])
        node_value_to_attr(section[10], 'valuta')
        doc.append(section)
    out += ET.tostring(doc, encoding='unicode')
    return out
 
def select_fields(lst, numbers):
    out = [i for n, i in enumerate(lst, 1)
           if n in numbers]
    return out
 
def make_xml_section(parent, names, lst):
    sub = ET.Element(parent)
    for name, value in zip(names, lst):
        e = ET.Element(name)
        e.text = str(value)
        sub.append(e)
    return sub
 
def node_clean_html(node):
    if node.text:
        node.text = clean(node.text)
 
def clean(s):
    doc = lxml.html.fromstring(s)
    return ''.join(doc.xpath(r'.//text()'))
 
def node_value_to_attr(node, attr_name):
    pref, suff = node.text.rsplit(None, 1)
    node.set(attr_name, suff)
    node.text = pref
 
def write_xml(fname, xmldata):
    with open(fname, 'w', encoding='utf-8') as fout:
        print(xmldata, file == fout)
 
def main():
    ifname = 'zemla.csv'
    csv_nums = [1, 3, 10,
                11, 16, 17,
                18, 19, 20,
                21, 22]
 
    ofname = 'zemla.xml'
    xml_root = 'csv_data'
    xml_node = 'sub'
    xml_names = ['id', 'name', 'type',
                 'details', 'permit', 'number',
                 'electricity', 'gas', 'water',
                 'road', 'price']
 
    csv_stream = read_csv(ifname)
    xmldata = convert_csv_to_xml(
        csv_stream,
        csv_nums,
        xml_root,
        xml_node,
        xml_names
    )
    write_xml(ofname, xmldata)
 
if __name__ == '__main__':
    main()

Просто беда.
py.user.next
i.z
Код который я пробую запустить:
Заново скопируй из моего сообщения, этот неправильно отредактирован тобой.

i.z
TypeError: 'newline' is an invalid keyword argument for this function
Поставь третий питон вместо второго.
old_monty
py.user.next
Это не из-за модуля csv, а из-за того, что файл открыт без указания кодировки
Спасибо за поправку. Действительно, с русскими буквами работает:
>>> with open('myfile.csv', encoding = 'utf-8') as mf:
	mfreader = csv.reader(mf)
	print('\n'.join([str(s) for s in list(mfreader)]))
['Номер', 'Название', 'Описание', 'Владелец', 'Арендатор', 'КогдаВзял', 'КогдаВернул']
['1', 'Грабли', 'Новые', 'Федя', 'Юля', '6/15/2015', '6/16/2015']
['2', 'Газонокосилка', 'Большая на колесах', 'Иван', 'Борис', '7/20/2015', '7/28/2015']
['3', 'Молоток', 'Новый, из нержавеющей стали', 'Алик', 'Федя', '9/29/2015', '']
['4', 'Лейка', 'Старая, немного протекает', 'Федя', '', '', '']
>>> 
Мое первоначальное утверждение было сделано на основании документации https://www.python.org/dev/peps/pep-0305/#to-do-notes-for-the-interested-and-ambitious, где сказано
To Do (Notes for the Interested and Ambitious)
Unicode. ugh.
а эта страница, оказывается, последний раз редактировалась в 2003 году, но при этом имеет статус “Final” (окончательная)!
py.user.next
old_monty
print('\n'.join([str(s) for s in list(mfreader)]))
>>> lst = [['a', 'b'], ['c', 'd'], ['e', 'f']]
>>> 
>>> print(*lst, sep='\n')
['a', 'b']
['c', 'd']
['e', 'f']
>>>
old_monty
py.user.next
>>> print(*lst, sep='\n')
Да, так намного проще и элегантнее, спасибо.
doza_and
old_monty
Да, так намного проще и элегантнее, спасибо.
Может оно и элегантнее но у результата есть недостаток - это синтаксически невалидный текст.
То что получилось и не csv и не json и не jaml. И смысла особого в такой организации вывода вроде нет.
В результате тот кто потом будет разбирать ваше художество будет вас проклянет. Поверьте таких художников в больших проектах бывает сотни. И для каждого надо будет специфический код чтения данных. Я встречал проекты с передачей данных в виде файлов в которых 2/3 кода форматирование вывода и потом борьба за чтение данных из этого формата.
На мой взгляд лучше:
>>> a=[['a', 'b'], ['c', 'd'], ['e', 'f']]
>>> print(a)
[['a', 'b'], ['c', 'd'], ['e', 'f']]
# валидный питоновский код можно зажевать eval
# хотите много строчек ок
>>> import json
>>> print(json.dumps(a,indent=2))
[
  [
    "a", 
    "b"
  ], 
  [
    "c", 
    "d"
  ], 
  [
    "e", 
    "f"
  ]
]
# такие данные тоже читаются одной строчкой.
# хочется таблицу ок
>>> import pandas as pd
>>> pd.DataFrame(a)
   0  1
0  a  b
1  c  d
2  e  f
# данные тоже считываются одной строчкой 
# нужен компромис между таблицей и структуированными данными:
>>> import yaml
>>> print(yaml.dump(a,indent=1))
- [a, b]
- [c, d]
- [e, f]

Выдумывание своих форматов данных очень плохая практика на мой взгляд. Лучше к такому не приучатся.
На мой взгляд формат в виде таблицы намного лучше чем xml. От хорошей жизни в него данные не конвертируют. Уместно преобразование в форматы баз данных, json и т.п. Если есть возможность подумайте о смене архитектуры обращения с данными. Просто сравните сколько приходится писать для xml и 2-3 строчки для обращения с другими форматами.
py.user.next
doza_and
это синтаксически невалидный текст
Не, можно придумать грамматику, в которой это будет валидно.
Просто он решил так вывести, чтобы было видно, где границы записи и где границы полей записи.

doza_and
На мой взгляд формат в виде таблицы намного лучше чем xml. От хорошей жизни в него данные не конвертируют.
А xml может использоваться для сериализации в каком-нибудь протоколе.
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB