Заполнение базы данных SQLite3 из файла .txt с помощью Python - PullRequest
13 голосов
/ 17 июля 2010

Я пытаюсь настроить веб-сайт в django, который позволяет пользователю отправлять запросы в базу данных, содержащую информацию об их представителях в Европейском парламенте.У меня есть данные в файле с разделением запятыми .txt в следующем формате:

Парламент, Имя, Страна, Партийная группа, Национальная партия, Должность

7, Марта Андреасен, ВеликобританияГруппа Европы за свободу и демократию, Партия независимости Соединенного Королевства, член

и т. Д.

Я хочу заполнить базу данных SQLite3 этими данными, но пока все учебные пособияЯ нашел только шоу, как это сделать вручную.Поскольку у меня в файле 736 наблюдений, я действительно не хочу этого делать.

Я подозреваю, что это простой вопрос, но я был бы очень признателен, если бы кто-то показал мне, как это сделать.

Thomas

Ответы [ 6 ]

20 голосов
/ 17 июля 2010

Итак, если ваш models.py выглядит примерно так:

class Representative(models.Model):
    parliament = models.CharField(max_length=128)
    name = models.CharField(max_length=128)
    country = models.CharField(max_length=128)
    party_group = models.CharField(max_length=128)
    national_party = models.CharField(max_length=128)
    position = models.CharField(max_length=128)

Затем вы можете запустить python manage.py shell и выполнить следующее:

import csv
from your_app.models import Representative
# If you're using different field names, change this list accordingly.
# The order must also match the column order in the CSV file.
fields = ['parliament', 'name', 'country', 'party_group', 'national_party', 'position']
for row in csv.reader(open('your_file.csv')):
    Representative.objects.create(**dict(zip(fields, row)))

И все готово.

Приложение (правка)

По просьбе Томаса, вот объяснение того, что делает **dict(zip(fields,row)):

Итак, изначально fields содержит список имен полей, которые мы определили, а row содержит список значений, представляющих текущую строку в файле CSV.

fields = ['parliament', 'name', 'country', ...]
row = ['7', 'Marta Andreasen', 'United Kingdom', ...]

Что делает zip(), так это объединяет два списка в один список пар элементов из обоих списков (например, молнию); то есть zip(['a','b,'c'], ['A','B','C']) вернет [('a','A'), ('b','B'), ('c','C')]. Итак, в нашем случае:

>>> zip(fields, row)
[('parliament', '7'), ('name', 'Marta Andreasen'), ('country', 'United Kingdom'), ...]

Функция dict() просто преобразует список пар в словарь.

>>> dict(zip(fields, row))
{'parliament': '7', 'name': 'Marta Andreasen', 'country': 'United Kingdom', ...}

** - это способ преобразования словаря в список аргументов ключевого слова для функции. Так что function(**{'key': 'value'}) является эквивалентом function(key='value'). Итак, в нашем примере вызов create(**dict(zip(field, row))) эквивалентен:

create(parliament='7', name='Marta Andreasen', country='United Kingdom', ...)

Надеюсь, это прояснит ситуацию.

4 голосов
/ 17 июля 2010

Как говорит SiggyF и только немного по-другому, чем Йошуа:

Создайте текстовый файл со своей схемой, например:

CREATE TABLE politicians (
    Parliament text, 
    Name text, 
    Country text, 
    Party_Group text, 
    National_Party text, 
    Position text
);

Создать таблицу:

>>> import csv, sqlite3
>>> conn = sqlite3.connect('my.db')
>>> c = conn.cursor()
>>> with open('myschema.sql') as f:            # read in schema file 
...   schema = f.read()
... 
>>> c.execute(schema)                          # create table per schema 
<sqlite3.Cursor object at 0x1392f50>
>>> conn.commit()                              # commit table creation

Используйте модуль CSV для чтения файла с данными для вставки:

>>> csv_reader = csv.reader(open('myfile.txt'), skipinitialspace=True)
>>> csv_reader.next()                          # skip the first line in the file
['Parliament', 'Name', 'Country', ...

# put all data in a tuple
# edit: decoding from utf-8 file to unicode
>>> to_db = tuple([i.decode('utf-8') for i in line] for line in csv_reader)
>>> to_db                                      # this will be inserted into table
[(u'7', u'Marta Andreasen', u'United Kingdom', ...

Вставить данные:

>>> c.executemany("INSERT INTO politicians VALUES (?,?,?,?,?,?);", to_db)
<sqlite3.Cursor object at 0x1392f50>
>>> conn.commit()

Убедитесь, что все прошло как ожидалось:

>>> c.execute('SELECT * FROM politicians').fetchall()
[(u'7', u'Marta Andreasen', u'United Kingdom', ...

Редактировать
А так как вы декодировали (в юникод) на входе, вы должны быть уверены, что кодировали на выходе. Например:

with open('encoded_output.txt', 'w') as f:
  for row in c.execute('SELECT * FROM politicians').fetchall():
    for col in row:
      f.write(col.encode('utf-8'))
      f.write('\n')
2 голосов
/ 18 июля 2010

Вы спросили, что сделала строка create (** dict (zip (fields, row))).

Я не знаю, как ответить прямо на ваш комментарий, поэтому постараюсь ответить на него здесь.

zip принимает несколько списков в качестве аргументов и возвращает список их соответствующих элементов в виде кортежей.

zip (list1, list2) => [(list1 [0], list2 [0]), (list1 [1], list2 [1]), ....]

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

create - это функция, которая принимает ключевые аргументы. Вы можете использовать ** some_dictionary для передачи этого словаря в функцию в качестве аргументов ключевого слова.

create (** {'name': 'john', 'age': 5}) => create (name = 'john', age = 5)

2 голосов
/ 17 июля 2010

Вы можете прочитать данные, используя модуль CSV. Затем вы можете создать SQL-оператор вставки и использовать метод executemany :

  cursor.executemany(sql, rows)

или используйте add_all , если вы используете sqlalchemy.

0 голосов
/ 29 декабря 2018

Если вы хотите сделать это простым методом с использованием sqlite3, вы можете сделать это, выполнив следующие 3 шага:

$ sqlite3 db.sqlite3
sqlite> .separator ","
sqlite> .import myfile.txt table_name

Однако помните следующее:

  1. Файл .txt должен находиться в том же каталоге , что и ваши db.sqlite3,
    в противном случае используйте абсолютный путь "/path/myfile.txt" при импорте
  2. Ваша схема для таблиц (количество столбцов) должна соответствовать количеству значений, разделенных запятыми в каждой строке в текстовом файле

Вы можете использовать команду .tables для проверки вашего имени таблицы

SQLite version 3.23.1 2018-04-10 17:39:29
Enter ".help" for usage hints.
sqlite> .tables
auth_group                  table_name               
auth_group_permissions      django_admin_log          
auth_permission             django_content_type       
auth_user                   django_migrations         
auth_user_groups            django_session            
auth_user_user_permissions
0 голосов
/ 17 июля 2010

Должно работать что-то вроде следующего: (не проверено)

# Open database (will be created if not exists)
conn = sqlite3.connect('/path/to/your_file.db')

c = conn.cursor()

# Create table
c.execute('''create table representatives
(parliament text, name text, country text, party_group text, national_party text, position text)''')

f = open("thefile.txt")
for i in f.readlines():
    # Insert a row of data
    c.execute("""insert into representatives
                 values (?,?,?,?,?,?)""", *i.split(", ")) # *i.split(", ") does unpack the list as arguments

# Save (commit) the changes
conn.commit()

# We can also close the cursor if we are done with it
c.close()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...