Подтвердить что ты не робот

Можно ли импортировать CSV файл и автоматически вывести разделитель?

Я хочу импортировать два типа CSV файлов, некоторые используют ";" для разделителя и других используйте ",". До сих пор я переключался между следующими двумя строками:

reader=csv.reader(f,delimiter=';')

или

reader=csv.reader(f,delimiter=',')

Можно ли не указывать разделитель и позволить программе проверять правильный разделитель?

Решения ниже (Blender и sharth), похоже, хорошо работают для разделенных запятыми файлов (сгенерированных с помощью Libroffice), но не для разделенных точкой с запятой файлов (сгенерированных с помощью MS Office). Вот первые строки одного файла с разделителями с запятой:

ReleveAnnee;ReleveMois;NoOrdre;TitreRMC;AdopCSRegleVote;AdopCSAbs;AdoptCSContre;NoCELEX;ProposAnnee;ProposChrono;ProposOrigine;NoUniqueAnnee;NoUniqueType;NoUniqueChrono;PropoSplittee;Suite2LecturePE;Council PATH;Notes
1999;1;1;1999/83/EC: Council Decision of 18 January 1999 authorising the Kingdom of Denmark to apply or to continue to apply reductions in, or exemptions from, excise duties on certain mineral oils used for specific purposes, in accordance with the procedure provided for in Article 8(4) of Directive 92/81/EEC;U;;;31999D0083;1998;577;COM;NULL;CS;NULL;;;;Propos* are missing on Celex document
1999;1;2;1999/81/EC: Council Decision of 18 January 1999 authorising the Kingdom of Spain to apply a measure derogating from Articles 2 and 28a(1) of the Sixth Directive (77/388/EEC) on the harmonisation of the laws of the Member States relating to turnover taxes;U;;;31999D0081;1998;184;COM;NULL;CS;NULL;;;;Propos* are missing on Celex document
4b9b3361

Ответ 1

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

def detectDelimiter(csvFile):
    with open(csvFile, 'r') as myCsvfile:
        header=myCsvfile.readline()
        if header.find(";")!=-1:
            return ";"
        if header.find(",")!=-1:
            return ","
    #default delimiter (MS Office export)
    return ";"

Ответ 2

Модуль csv, по-видимому, рекомендует использовать csv сниффер для этой проблемы.

Они приводят следующий пример, который я адаптировал для вашего случая.

with open('example.csv', 'rb') as csvfile:
    dialect = csv.Sniffer().sniff(csvfile.read(1024), delimiters=";,")
    csvfile.seek(0)
    reader = csv.reader(csvfile, dialect)
    # ... process CSV file contents here ...

Попробуй.

[9:13am][[email protected] /tmp] cat example 
#!/usr/bin/env python
import csv

def parse(filename):
    with open(filename, 'rb') as csvfile:
        dialect = csv.Sniffer().sniff(csvfile.read(), delimiters=';,')
        csvfile.seek(0)
        reader = csv.reader(csvfile, dialect)

        for line in reader:
            print line

def main():
    print 'Comma Version:'
    parse('comma_separated.csv')

    print
    print 'Semicolon Version:'
    parse('semicolon_separated.csv')

    print
    print 'An example from the question (kingdom.csv)'
    parse('kingdom.csv')

if __name__ == '__main__':
    main()

И наши примеры ввода

[9:13am][[email protected] /tmp] cat comma_separated.csv 
test,box,foo
round,the,bend

[9:13am][[email protected] /tmp] cat semicolon_separated.csv 
round;the;bend
who;are;you

[9:22am][[email protected] /tmp] cat kingdom.csv 
ReleveAnnee;ReleveMois;NoOrdre;TitreRMC;AdopCSRegleVote;AdopCSAbs;AdoptCSContre;NoCELEX;ProposAnnee;ProposChrono;ProposOrigine;NoUniqueAnnee;NoUniqueType;NoUniqueChrono;PropoSplittee;Suite2LecturePE;Council PATH;Notes
1999;1;1;1999/83/EC: Council Decision of 18 January 1999 authorising the Kingdom of Denmark to apply or to continue to apply reductions in, or exemptions from, excise duties on certain mineral oils used for specific purposes, in accordance with the procedure provided for in Article 8(4) of Directive 92/81/EEC;U;;;31999D0083;1998;577;COM;NULL;CS;NULL;;;;Propos* are missing on Celex document
1999;1;2;1999/81/EC: Council Decision of 18 January 1999 authorising the Kingdom of Spain to apply a measure derogating from Articles 2 and 28a(1) of the Sixth Directive (77/388/EEC) on the harmonisation of the laws of the Member States relating to turnover taxes;U;;;31999D0081;1998;184;COM;NULL;CS;NULL;;;;Propos* are missing on Celex document

И если мы выполним пример программы:

[9:14am][[email protected] /tmp] ./example 
Comma Version:
['test', 'box', 'foo']
['round', 'the', 'bend']

Semicolon Version:
['round', 'the', 'bend']
['who', 'are', 'you']

An example from the question (kingdom.csv)
['ReleveAnnee', 'ReleveMois', 'NoOrdre', 'TitreRMC', 'AdopCSRegleVote', 'AdopCSAbs', 'AdoptCSContre', 'NoCELEX', 'ProposAnnee', 'ProposChrono', 'ProposOrigine', 'NoUniqueAnnee', 'NoUniqueType', 'NoUniqueChrono', 'PropoSplittee', 'Suite2LecturePE', 'Council PATH', 'Notes']
['1999', '1', '1', '1999/83/EC: Council Decision of 18 January 1999 authorising the Kingdom of Denmark to apply or to continue to apply reductions in, or exemptions from, excise duties on certain mineral oils used for specific purposes, in accordance with the procedure provided for in Article 8(4) of Directive 92/81/EEC', 'U', '', '', '31999D0083', '1998', '577', 'COM', 'NULL', 'CS', 'NULL', '', '', '', 'Propos* are missing on Celex document']
['1999', '1', '2', '1999/81/EC: Council Decision of 18 January 1999 authorising the Kingdom of Spain to apply a measure derogating from Articles 2 and 28a(1) of the Sixth Directive (77/388/EEC) on the harmonisation of the laws of the Member States relating to turnover taxes', 'U', '', '', '31999D0081', '1998', '184', 'COM', 'NULL', 'CS', 'NULL', '', '', '', 'Propos* are missing on Celex document']

Также возможно стоит отметить, какую версию python я использую.

[9:20am][[email protected] /tmp] python -V
Python 2.7.2

Ответ 3

Учитывая проект, который имеет дело с обоими, (запятыми) и | (вертикальная строка), которые хорошо сформированы, я попробовал следующее (как указано в https://docs.python.org/2/library/csv.html#csv.Sniffer):

dialect = csv.Sniffer().sniff(csvfile.read(1024), delimiters=',|')

Однако в файле -delimited было возвращено исключение "Не удалось определить разделитель". Казалось разумным предположить, что эвристика нюха может работать лучше всего, если каждая строка имеет такое же количество разделителей (не считая того, что может быть заключено в кавычки). Итак, вместо того, чтобы читать первые 1024 байта файла, я пробовал прочитать первые две строки целиком:

temp_lines = csvfile.readline() + '\n' + csvfile.readline()
dialect = csv.Sniffer().sniff(temp_lines, delimiters=',|')

Пока это хорошо работает для меня.

Ответ 4

И если вы используете DictReader, вы можете сделать это:

#!/usr/bin/env python
import csv

def parse(filename):
    with open(filename, 'rb') as csvfile:
        dialect = csv.Sniffer().sniff(csvfile.read(), delimiters=';,')
        csvfile.seek(0)
        reader = csv.DictReader(csvfile, dialect=dialect)

        for line in reader:
            print(line['ReleveAnnee'])

Я использовал это с Python 3.5, и он работал таким образом.

Ответ 5

Я не думаю, что это может быть совершенно общее решение (одна из причин, по которой я могу использовать , как разделитель, заключается в том, что некоторые из моих полей данных должны включать ;...). Простой эвристик для решения может состоять в том, чтобы просто прочитать первую строку (или больше), подсчитать количество содержащихся в ней символов , и ; (возможно, игнорируя те внутри кавычек, если что-то создает ваши файлы .csv последовательно) и угадать, что наиболее частым из них является правильный разделитель.