Форум программистов, компьютерный форум, киберфорум
Python для начинающих
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.59/29: Рейтинг темы: голосов - 29, средняя оценка - 4.59
0 / 0 / 0
Регистрация: 22.12.2017
Сообщений: 4
1

Замена значений колонки в dbf файле

22.12.2017, 16:23. Показов 5707. Ответов 8
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Добрый день, начал изучать Python и возникла задача по работе привести в порядок номенклатурные позиции, которую попробовал решить с помощью Python 3.6
Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#Чтение из ДБФ и изменение строкового поля
import dbf
import re
db=dbf.Table('nobase') 
db.open()
D={}            
pole='artikul'
nycmo=" "*18
for rec in db:      #   загоняет столбец в словарь
    prov=list(D.values()) #проверка на уникальность
    recnew=""
    if rec[pole].isdigit(): #числовое
        D[rec[pole]]=rec[pole]
        continue
    elif rec[pole].istitle(): #с заглавной
        recnew=reborn(rec[pole])
    else: #все остальное
        recnew=rec[pole].strip()
        recnew=titl(recnew)
        recnew=reborn(recnew)
    if recnew:
        if recnew in prov:
            recnew=numadd(recnew,prov)
        recnew1=recnew+nycmo
        D[rec[pole]]=recnew1[:18] #длинна поля 18 символов
    print("|",rec[pole],"|",'\t',"|",D[rec[pole]],"|",'\t', len(D[rec[pole]]))
    rec._update_field_value(rec._recnum,pole,D[rec[pole]])
    rec._write()
при отладке получаю ошибку на 17ой записи. И не могу понять почему именно на 17, в интерпретаторе выглядит так
Кликните здесь для просмотра всего текста

>>> import renamef
| Молочная продукция | | Молочная продукция | 18
| Компьютер | | Компьютер | 18
| Клавиатура | | Клавиатура | 18
| Мышь | | Мышь | 18
| Cd-rom | | Cd-rom | 18
| Измерителье7-12 | | Измерителье7-12 | 18
| Программное обе | | Программное обе | 18
| Система анализа | | Система анализа | 18
| Программа sm | | Программа sm | 18
| Рентгеновские т | | Рентгеновские т | 18
| Ксерокс Саnon | | Ксерокс Саnon | 18
| Исследовательск | | Исследовательск | 18
| Кондиционер lg | | Кондиционер lg | 18
| Комплект печног | | Комплект печног | 18
| Кальциметр коук | | Кальциметр коук | 18
| Компьютор атх | | Компьютор атх | 18
| компьютор athlo... | | Компьютор athlo | 18
Traceback (most recent call last):
File "<pyshell#1>", line 1, in <module>
import renamef
File "C:\pyton\renamef.py", line 64, in <module>
rec._update_field_value(rec._recnum,pole,D[rec[pole]])
File "C:\pyton\lib\site-packages\dbf\ver_33.py", line 2706, in _update_field_value
null_data[byte] &= 0xff ^ 1 << bit
IndexError: array index out of range

Первые 16 записей нормально заменились, в спойлере запускаю уже с измененным файлом.
Причем словарь создался как надо, отдельно проверял, ключи соответствуют значениям поля. Файл содержит более 9000 строк
Использую dbf-0.96.8-py3. Может кто-то подскажет или другой способ с помощью Python 3.6 заменить значения в поле, или что я неправильно делаю.
…Да, я в курсе, что dbf прошлый век, можете об этом не упоминать.
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
22.12.2017, 16:23
Ответы с готовыми решениями:

Проверить на наличие колонки в DBF файле
При загрузке файлов формата DBF в нескольких файлах существует колонка ДБФ.PR_DDK, а в некоторых...

Замена значений колонки
Доброго времени суток!Имеется база данных postgresql с таблицей в которой нужно заменить значения...

Select и Update в dbf файле (условие нескольких значений: 5, 8, 15.)
Не особо силен в запросах, но нужно бы среди множества в поле типа &quot;Число&quot; обновились сведения. ...

Поиск значений в файле и замена соответствующих в другом файле
Сильно не пинайте, я новичок. Существует 2 файла. В первом (1.txt) текст: 123=qwerty...

Как определить сумму значений одной колонки в рамках значений другой колонки?
Как определить сумму значений одной колонки в рамках значений другой колонки c# datagridview через...

8
Эксперт Python
4632 / 2050 / 361
Регистрация: 17.03.2012
Сообщений: 10,134
Записей в блоге: 6
22.12.2017, 17:07 2
Разбирайтесь с проблемной записью, больше ничего не посоветуешь.
0
928 / 690 / 269
Регистрация: 10.12.2016
Сообщений: 1,699
23.12.2017, 13:21 3
может проще экспорт в csv, и из него сделать что надо?

Добавлено через 21 минуту
Python
1
2
3
4
5
6
7
8
9
10
11
12
13
import dbf
 
db = dbf.Table('test.dbf', 'name C(30);age N(3,0);born D', codepage='cp866')
db.open()
for datum in (
        ('Петя', 31, dbf.Date(1979, 9, 13)),
        ('Иван Иваныч', 57, dbf.Date(1954, 7, 2)),
        ('Вася Пупкин', 44, dbf.Date(1967, 1, 9)),
    ): db.append(datum)
dbf.export(db,filename='test.csv',encoding='utf-8')
db.close()
with open('test.csv') as f:
    for row in f: print(row)
Python
1
2
3
4
5
6
7
"name","age","born"
 
"Петя                          ",31,"1979-09-13"
 
"Иван Иваныч                   ",57,"1954-07-02"
 
"Вася Пупкин                   ",44,"1967-01-09"
Добавлено через 1 час 39 минут
по феншую
Python
1
2
3
4
5
6
7
8
9
10
11
12
13
db = dbf.Table('test.dbf', 'name C(30);age N(3,0);born D', codepage='cp866')
db.open()
for datum in (
        ('Петя', 31, dbf.Date(1979, 9, 13)),
        ('Иван Иваныч', 57, dbf.Date(1954, 7, 2)),
        ('Вася Пупкин', 44, dbf.Date(1967, 1, 9)),
    ): db.append(datum)
dbf.export(db,filename='test.csv',encoding='utf-8')
db.close()
with open('test.csv') as f:
    rd = csv.reader(f)
    for row in rd:
        print(row)
Python
1
2
3
4
['name', 'age', 'born']
['Петя                          ', '31', '1979-09-13']
['Иван Иваныч                   ', '57', '1954-07-02']
['Вася Пупкин                   ', '44', '1967-01-09']
0
0 / 0 / 0
Регистрация: 22.12.2017
Сообщений: 4
23.12.2017, 13:51  [ТС] 4
проблема в том что любая запись >16 не меняется, если я меняю на любое число условие
Python
1
2
3
4
if rec._recnum>200:
        print("|",rec[pole],"|",'\t',"|",D[rec[pole]],"|",'\t', rec._recnum)
        rec._update_field_value(rec._recnum,pole,D[rec[pole]])
        rec._write()
то получаю ту же ошибку сразу на первой же записи которую хочу изменить.
может проще экспорт в csv, и из него сделать что надо?
не совсем понимаю как. Мне нужно сделать временную таблицу csv а потом снова создать нужный файл dbf
описывая все поля файла? файл достаточно объемный, два десятка полей:
{ "RN", "C", 4, 0 },;
{ "PARENT_RN", "C", 4, 0 },;
{ "MNOB_RN", "C", 4, 0 },;
{ "TNWD_RN", "C", 4, 0 },;
{ "OKDP_RN", "C", 4, 0 },;
{ "OKPD_RN", "C", 4, 0 },;
{ "TAXGRP_RN", "C", 4, 0 },;
{ "GDGR_RN", "C", 4, 0 },;
{ "RN_MES", "C", 4, 0 },;
{ "NAME_NOM", "C", 240, 0 },;
{ "ARTIKUL", "C", 18, 0 },;
{ "ADD_CODE", "C", 15, 0 },;
{ "TYPE", "C", 1, 0 },;
{ "PRICE_TYPE", "I", 4, 0 },;
{ "PERADDPRIC", "N", 6, 2 },;
{ "COUNTRY_RN", "C", 4, 0 },;
{ "KLASS_PR", "C", 4, 0 },;
{ "PRIMECH", "M", 4, 0 },;
{ "_NullFlags", "0", 2, 0 } ;
0
928 / 690 / 269
Регистрация: 10.12.2016
Сообщений: 1,699
23.12.2017, 14:43 5
сохраните структуру отдельно, при необходимости дублируете
Python
1
2
3
4
5
db = dbf.Table('test.dbf')
db.open()
print(db.structure())
db.close()
>>>['name C(30)', 'age N(3,0)', 'born D']
dbf нужен сейчас разве что в 1С. такая БД как вы описали - это электронная таблица, а не база данных,
я бы в sqlite3 хотя бы перегнал
0
0 / 0 / 0
Регистрация: 22.12.2017
Сообщений: 4
24.12.2017, 10:17  [ТС] 6
Вообще задача стоит так: из бд копирую файл с номенклатурными данными, хочу изменить поле артикул и потом заменить файл обратно. бд позволяет такое без потери работоспособности. Я только начинаю с Python работать до этого не занимался программированием. Читаю Лутса дошел до классов. Поэтому не совсем понимаю как из sqlite3 затем обратно dbf сделать. На Python очень легко с помощью re поменять артикул как мне надо и 9000 записей быстро исправляются. Сначала я просто практиковался, а потом пришла мысль почему бы не привести складскую номенклатуру в порядок но вот запись обратно в файл оказалась проблематично. Поэтому и обратился на форум за помощью. ошибку вызывает замена записи
Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
def _update_field_value(self, index, name, value):
        """
        calls appropriate routine to convert value to bytes, and save it in record
        """
        fielddef = self._meta[name]
        field_type = fielddef[TYPE]
        flags = fielddef[FLAGS]
        binary = flags & BINARY
        nullable = flags & NULLABLE and '_nullflags' in self._meta
        update = self._meta.fieldtypes[field_type]['Update']
        if nullable:
            byte, bit = divmod(index, 8)
            null_def = self._meta['_nullflags']
            null_data = self._data[null_def[START]:null_def[END]]
            if value is Null:
                null_data[byte] |= 1 << bit
                value = None
            else:
                null_data[byte] &= 0xff ^ 1 << bit
            self._data[null_def[START]:null_def[END]] = null_data
        if value is not Null:
            bytes = array('B', update(value, fielddef, self._meta.memo, self._meta.input_decoder, self._meta.encoder))
            size = fielddef[LENGTH]
            if len(bytes) > size:
                raise DataOverflowError("tried to store %d bytes in %d byte field" % (len(bytes), size))
            blank = array('B', b' ' * size)
            start = fielddef[START]
            end = start + size
            blank[:len(bytes)] = bytes[:]
            self._data[start:end] = blank[:]
        self._dirty = True
Но вот знаний понять, почему, пока нет.Единственное что понял, что это связано с тем что value становится null
0
928 / 690 / 269
Регистрация: 10.12.2016
Сообщений: 1,699
24.12.2017, 14:34 7
для dbf есть свой ЯП, питоновская обертка то ли кривая, то ли авторы давно забили на нее. реально у меня получилось записать/прочитать dbf-файл без гемора.
http://alimuradov.ru/2016/12/0... -python-3/
дело конечно ваше, я бы работал с csv или sqlite3 в данном случае, dbf - только для отчетов где он нужен.

Добавлено через 1 час 6 минут
нашел я метод, но в доках его нет
Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import dbf
 
def create_db():
    db = dbf.Table('test.dbf', 'name C(30);age N(3,0);born D', codepage='cp866')
    db.open()
    for datum in (
            ('Петя Козлодоев', 31, dbf.Date(1979, 9, 13)),
            ('Иван Иваныч', 57, dbf.Date(1954, 7, 2)),
            ('Вася Пупкин', 44, dbf.Date(1967, 1, 9)),
        ): db.append(datum)
    db.close()
 
if  __name__=="__main__":
    create_db()
    db = dbf.Table('test.dbf')
    db.open()
    for rec in db:
        print(rec.name,rec.age,rec.born)
    print('update:')
    for rec in db:
        with rec as r:
            r.age += 3
    for rec in db:
        print(rec.name,rec.age,rec.born)
    db.close()
Добавлено через 2 часа 9 минут
Цитата Сообщение от Винни-пух Посмотреть сообщение
Но вот знаний понять, почему, пока нет.Единственное что понял, что это связано с тем что value становится null
ф-ции начиющиеся с _ - приватные и юзеру их лучше не использовать. нашел еще метод для удаления записей, тоже без
with не работает. доки dbf никакие просто
http://pythonhosted.org/dbf/

Добавлено через 29 минут
Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
if  __name__=="__main__":
    #create_db()
    db = dbf.Table('test.dbf')
    db.open()
    for rec in db:
        print(rec.name,rec.age,rec.born)
 
    for rec in db:
        with rec as r:
            r.age += 3 #меняем значение поля
            if r.age > 60:
                dbf.delete(r) #помечаем на удаление
    db.close()
 
    print('pack:')
    db.open()
    db.pack() # удаляем помеченные
    for rec in db:
        print(rec.name,rec.age,rec.born)
    db.close()
0
0 / 0 / 0
Регистрация: 22.12.2017
Сообщений: 4
27.12.2017, 10:12  [ТС] 8
Попробую перезапись всей таблицы, по результатам отпишусь.
0
928 / 690 / 269
Регистрация: 10.12.2016
Сообщений: 1,699
27.12.2017, 14:56 9
на 10000 у мну робит, но vs sqlite3 - тормоз
Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
import dbf
from random import randint,sample
from datetime import datetime
from time import time
 
lst = [chr(i) for i in range(ord('a'),ord('z')+1)]
 
def create_db():
    db = dbf.Table('test.dbf', 'id N(5,0); name C(30);age N(3,0);date D',codepage='cp866')
    db.open()
    for i in range(0,10000):
        name = ''.join(sample(lst,8))
        age = randint(21,60)
        data = (i+1,name,age,dbf.Date(datetime.now()))
        db.append(data)
    db.close()
 
if  __name__=="__main__":
    t0 = time()
    create_db()
    db = dbf.Table('test.dbf')
    db.open()
    for rec in db:
        with rec as r:
            r.age += 3 #меняем значение поля
            if r.age > 60:
                print('\t',' '.join([str(i) for i in rec]))
                dbf.delete(r) #помечаем на удаление
    db.close()
    print('pack:')
    db.open()
    db.pack() # удаляем помеченные
    print('len:',len(db),'time:',time() - t0)
    db.close()
Python
1
2
pack:
len: 9269 time: 20.98514699935913
Добавлено через 1 час 54 минуты
то же с sqlite3
Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
import sqlite3
from random import randint, sample
from datetime import datetime
from time import time
 
lst = [chr(i) for i in range(ord('а'), ord('я') + 1)]
 
 
def create_db():
    conn = sqlite3.connect('test.db')
    cur = conn.cursor()
    cur.execute("drop table if exists test")
    sql = '''create table test(id integer primary key autoincrement,name char[40],age numeric,date date)'''
    cur.execute(sql)
    for i in range(10000):
        name = ''.join(sample(lst, 10)).title()
        age = randint(21, 60)
        try:
            cur.execute('''insert into test values(?,?,?,date("now"))''', (None, name, age,))
        except Exception as e:
            print(e)
    conn.commit()
    conn.close()
 
 
if __name__ == "__main__":
    t0 = time()
    create_db()
    conn = sqlite3.connect('test.db')
    cur = conn.cursor()
    cur.execute('''update test set age = age + 3''')
    cur.execute('''delete from test where age > 60''')
    conn.commit()
    cur.execute("select count(*) from test")
    print("len:", end=' ')
    print(cur.fetchone()[0])
    conn.close()
    print('time:', time() - t0)
Python
1
2
len: 9257
time: 0.397202730178833
0
27.12.2017, 14:56
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
27.12.2017, 14:56
Помогаю со студенческими работами здесь

Поиск и замена значений в файле
Есть файл скрипта CAD'овской программы в формате *.vbs Файл содержит примерно такую инфу: ...

Поиск и замена значений в файле
Приветствую всех ! Нужна процедура которая бы искала в текстовом файле указанное слово и заменяла...

Замена значений в RTF файле
Доброго дня! Есть несколько rtf док-ов (которые по факту можно переделать в любой другой формат,...

Замена значений в бинарном файле
В бинарном файле записаны целые числа. Заменить положительные числа на 0. я придумал как...

Замена отрицательных значений в файле нулями
Написал код, для замены отрицательных значений в файле нулями...не могу понять где ошибки,...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
9
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru