Ошибка dbfpy при конвертации dbf из UTF8 в Win1251

Вопросы по нескольким пакетам сразу, или вопросы, которые непонятно к какой ГИС отнести
Ответить
Аватара пользователя
Максим Дубинин
MindingMyOwnBusiness
Сообщения: 9129
Зарегистрирован: 06 окт 2003, 20:20
Репутация: 748
Ваше звание: NextGIS
Откуда: Москва
Контактная информация:

Ошибка dbfpy при конвертации dbf из UTF8 в Win1251

Сообщение Максим Дубинин » 15 дек 2008, 07:33

Кто-то использует dbgpy для подобного? В принципе очень удобно, но почему-то спотыкается на некоторых dbf из shape-файлов.

Скрипт такой:

Код: Выделить всё

#!/usr/bin/python
#--*-- encoding: utf-8 --*--

import sys
from dbfpy import dbf
from types import *

db = dbf.Dbf(sys.argv[1])
newDB=dbf.Dbf(sys.argv[2], new=True)

for f in db.header.fields:
   newDB.addField(f)

for rec in db:
   r=newDB.newRecord()
   newData=[]
   for f in rec.fieldData:
      if type(f)==StringType:
         f=unicode(f,'utf-8')
         f=f.encode('windows-1251')
      newData.append(f)
   r.fieldData=newData
   r.store()

db.close()
newDB.close()
Ошибка такая:
Traceback (most recent call last):
File "dbfer.py", line 14, in <module>
for rec in db:
File "/usr/local/lib/python2.5/site-packages/dbfpy/dbf.py", line 242, in __getitem__
return self.RecordClass.fromStream(self, self._fixIndex(index))
File "/usr/local/lib/python2.5/site-packages/dbfpy/record.py", line 121, in fromStream
return cls.fromString(dbf, cls.rawFromStream(dbf, index), index)
File "/usr/local/lib/python2.5/site-packages/dbfpy/record.py", line 140, in fromString
[_fd.decodeFromRecord(string) for _fd in dbf.header.fields])
File "/usr/local/lib/python2.5/site-packages/dbfpy/fields.py", line 169, in decodeFromRecord
return self.decodeValue(self.rawFromRecord(record))
File "/usr/local/lib/python2.5/site-packages/dbfpy/fields.py", line 243, in decodeValue
return int(value)
ValueError: invalid literal for int() with base 10: 'town'
Вложения
place_p.dbf
(506 байт) 884 скачивания
пристегивайтесь, турбулентность прямо по курсу

KolesovDmitry
Гуру
Сообщения: 810
Зарегистрирован: 22 авг 2007, 14:58
Репутация: 123
Откуда: Казань

Re: Ошибка dbfpy при конвертации dbf из UTF8 в Win1251

Сообщение KolesovDmitry » 15 дек 2008, 18:02

Толком ничего сказать не могу, но опишу ход рассуждений
Смотрю структуру файла:

Код: Выделить всё

6 Columns,  1 Records in file
             Id          string  (20,0)
           Type          string  (20,0)
           Name          string  (100,0)
       Int_namr          string  (20,0)
          place           float  (20,0)
          Is_in          string  (100,0)
Как мне кажется, в этом файле ошибку вызывает не обработка строковых значений, а обработка числового поля place.
Вот почему мне так кажется:

Как видно из приведенного списка вызова процедур, строка вызвавшая ошибку, такая:

Код: Выделить всё

  File "/usr/lib/python2.5/site-packages/dbfpy/fields.py", line 243, in decodeValue
    return int(value)
Т.е. ошибка возникает в файле fields.py в строке 243. Вот это процедура:

Код: Выделить всё

def decodeValue(self, value):
    """Return a number decoded from ``value``.
    If decimals is zero, value will be decoded as an integer;
    or as a float otherwise.
    Return:
    Return value is a int (long) or float instance.
    """
    value = value.strip()
    if self.decimalCount > 0:
        # a float (has decimal digits)
        if value:
            return float(value)
        return 0.0
    else:
        # an integer
        if value:
			### Вот это место, где возникает ошибка:####
            return int(value)
        return 0

В этой процедуре анализируется числовое значение, представленное в строковом виде, и приводится к числовому типу. Я посмотрел любопытства ради, что на момент совершения ошибки содержится в переменной value, оказалось, что там содержится значение "town". Понятно, что из строки "town" числа не получить!

Далее смотрим содержимое dbf-файла, оставив только текстовые символы, а все не-текстовые заменив на пробелы:
Type
Name
Int_namr
place
Is_in
191732832 node
town

видим, что в файле действительно есть слово town. Итак, предположение: видимо, происходит ошибка адресации полей dbf-файла, возможно, ошибка в самом файле (например структура файла не соответствует загловку) или же глюки в библиотеке dbfpy -- тут нужно разбираться подробнее.

Попробуй изменить программу, вставив в нее блок обработки искл. ситуации ValueError, может станет понятнее, что происходит:

Код: Выделить всё

#!/usr/bin/python
#--*-- encoding: utf-8 --*--

import sys
from dbfpy import dbf
from types import *

db = dbf.Dbf(sys.argv[1])
newDB=dbf.Dbf(sys.argv[2], new=True,ignoreErrors=True)


for f in db.header.fields:
    newDB.addField(f)

for i in range(len(db)):
    try:
        rec=db[i]
        r=newDB.newRecord()
        newData=[]
        for f in rec.fieldData:
                if type(f)==StringType:
                    f=unicode(f,'utf-8')
                    f=f.encode('windows-1251')
                newData.append(f)
                r.fieldData=newData
                r.store()
    except ValueError:
        print "Запись N %s: ошибка" % i

db.close()
newDB.close()

Аватара пользователя
Максим Дубинин
MindingMyOwnBusiness
Сообщения: 9129
Зарегистрирован: 06 окт 2003, 20:20
Репутация: 748
Ваше звание: NextGIS
Откуда: Москва
Контактная информация:

Re: Ошибка dbfpy при конвертации dbf из UTF8 в Win1251

Сообщение Максим Дубинин » 15 дек 2008, 19:10

Дима, выражаю глубочайшую признательность!

Действительно обращал внимание на incorrect int, но не догадался рыть более тщательно, но твоя самая первая иллюстрация структуры полей все моментально прояснила ситуацию и теперь все работает как надо.

Интересно, что Arcview плевать на то, что в поле float записаны текстовые значения, он их просто не показывает.
пристегивайтесь, турбулентность прямо по курсу

Ответить

Вернуться в «Общий - ПО»

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и 3 гостя