Unicode к UTF8 для файлов CSV - Python через xlrd

Я думал об ужасных временах, которые я провел в Числовом Аналитическом ходе.

И затем я помню, было это окружение функции вокруг 'сети от Исходного кода Quake:

float Q_rsqrt( float number )
{
  long i;
  float x2, y;
  const float threehalfs = 1.5F;

  x2 = number * 0.5F;
  y  = number;
  i  = * ( long * ) &y;  // evil floating point bit level hacking
  i  = 0x5f3759df - ( i >> 1 ); // wtf?
  y  = * ( float * ) &i;
  y  = y * ( threehalfs - ( x2 * y * y ) ); // 1st iteration
  // y  = y * ( threehalfs - ( x2 * y * y ) ); // 2nd iteration, this can be removed

  #ifndef Q3_VM
  #ifdef __linux__
    assert( !isnan(y) ); // bk010122 - FPE?
  #endif
  #endif
  return y;
}

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

Это должно быть применимым и могло бы даже быть быстрее, это от одной из феноменальной идентификационной игры программного обеспечения!

Это записано в C++, но не должно быть слишком трудно снова использовать ту же технику в Java, как только Вы получаете идею:

я первоначально нашел его в: http://www.codemaestro.com/reviews/9

метод Newton объяснил в Википедии: http://en.wikipedia.org/wiki/Newton%27s_method

можно перейти по ссылке для большего количества объяснения того, как это работает, но если Вы не заботитесь очень, тогда это примерно, что я помню от чтения блога и от взятия Числового Аналитического хода:

  • эти * (long*) &y в основном быстрая функция convert-long, таким образом, целочисленные операции могут быть применены на необработанные байты.
  • 0x5f3759df - (i >> 1); строка является предрасчетным значением семени для функции приближения.
  • эти * (float*) &i преобразовывает значение назад в плавающую точку.
  • y = y * ( threehalfs - ( x2 * y * y ) ) строка в основном выполняет итерации значения по функции снова.

функция приближения дает более точные значения, больше Вы выполняете итерации функции по результату. В случае Quake одно повторение "достаточно хорошо", но если бы это не было для Вас... тогда, то Вы могли бы добавить столько повторения, сколько Вам нужно.

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

18
задан anschauung 27 July 2009 в 17:48
поделиться

4 ответа

Я ожидаю, что возвращаемое значение cell_value будет строка Юникода, которая вызывает проблемы (напечатайте ее type () , чтобы подтвердить это), и в этом случае вы сможете решить эту проблему, изменив эту одну строку:

this_row.append(s.cell_value(row,col))

на:

this_row.append(s.cell_value(row,col).encode('utf8'))

Если cell_value возвращает несколько разных типов, тогда вам нужно закодировать тогда и только тогда, когда он возвращает строку Unicode; поэтому вы разделите эту строку на несколько строк:

val = s.cell_value(row, col)
if isinstance(val, unicode):
    val = val.encode('utf8')
this_row.append(val)
25
ответ дан 30 November 2019 в 07:39
поделиться

Вы просили объяснений, но некоторые из явлений необъяснимы без вашей помощи.

(A) Строки в файлах XLS, созданных в Excel 97 и более поздних версиях, кодируются в Latin1, если возможно, в противном случае в UTF16LE. Каждая строка имеет флаг, указывающий, что было использовано. Ранее в Excel строки кодировались в соответствии с «кодовой страницей» пользователя. В любом случае xlrd создает объекты Unicode . Кодировка файла представляет интерес только в том случае, если файл XLS был создан сторонним программным обеспечением, которое либо пропускает кодовую страницу, либо лжет о ней. См. Раздел Unicode в начале документации xlrd.

(B) Необъяснимое явление:

Этот код:

bcw = csv.writer(bc,csv.excel,b.encoding)

вызывает следующую ошибку в Python 2.5, 2.6 и 3.1: TypeError: ожидается не более 2 аргументов, получено 3 - это о том, чего я ожидал, учитывая документацию на csv.writer; он ожидает файловый объект, за которым следует либо (1) ничего (2) диалект, либо (3) один или несколько параметров форматирования. Вы указали ему диалект, а csv.writer не имеет аргумента кодировки, так что splat. Какую версию Python вы используете? Или вы не скопировали / вставили скрипт, который вы на самом деле запустили?

(C) Необъяснимые явления вокруг трассировки и каковы были фактические данные о нарушении:

"the_script.py", line 40, in <module>
this_row.append(str(s.cell_value(row,col)))
UnicodeEncodeError: 'ascii' codec can't encode character u'\xed' in position 5: ordinal not in range(128) 

Во-первых, в строке кода оскорбления есть str (), которая не была ' t в упрощенном скрипте - разве вы не скопировали / вставили скрипт, который вы действительно запускали? В любом случае не стоит использовать str вообще - вы выиграли ' t получить полную точность на ваших поплавках; просто позвольте модулю csv преобразовать их.

ВТОРОЙ, вы говорите "" "Кажется, что зацикливается значение" 516-777316 "- текст в исходном листе Excel" 516-7773167 "( с 7 на конце) "" "--- сложно представить, как 7 теряется на конце. Я бы использовал что-то вроде этого, чтобы выяснить, какие именно проблемные данные:

try:
    str_value = str(s.cell_value(row, col))
except:
    print "row=%d col=%d cell_value=%r" % (row, col, s.cell_value(row, col))
    raise

Этот% r избавляет вас от ввода cell_value =% s ... repr (s.cell_value (row, col)) ... repr () дает однозначное представление ваших данных. Узнать его. Используйте его.

Как вы пришли к «516-777316»?

В-третьих, сообщение об ошибке фактически содержит жалобу на символ юникода u '\ xed' со смещением 5 (т.е. шестой символ). U + 00ED - ЛАТИНСКАЯ СТРОЧНАЯ БУКВА I С ОСТРЫМ, и в «516-7773167»

ничего подобного нет. В-четвертых, место ошибки кажется движущейся целью - вы сказали в комментарии к одному из решений. : "Ошибка на bcw.writerow." А?

(D) Почему вы получили это сообщение об ошибке (с помощью str ()): str (a_unicode_object) пытается преобразовать объект Unicode в объект str и при отсутствии какой-либо информации о кодировке использует ascii, но у вас есть данные не в формате ascii, поэтому splat. Обратите внимание, что ваша цель - создать файл csv, закодированный в utf8, но ваш упрощенный сценарий нигде не упоминает utf8.

(E) "" "... s.cell (row, col)) (egscell вместо s.cell_value) весь документ записывается без ошибок. Результат не особенно желателен (текст: u '

(G) UTF8 не является Unicode. UTF16LE не является Unicode. UTF16 - это не Unicode ... и идея о том, что каждая отдельная строка будет тратить по 2 байта в спецификации UTF16, слишком абсурдна, чтобы даже MS могла подумать: -)

(H) Дальнейшее чтение (кроме xlrd docs):

http://www.joelonsoftware.com/articles/Unicode.html
http://www.amk.ca/python/howto/unicode
9
ответ дан 30 November 2019 в 07:39
поделиться

Похоже, у вас 2 проблемы.

Что-то напортачило в этой ячейке - '7' следует закодировать как u'x37 ', я думаю, поскольку это в ASCII- диапазон.

Что еще более важно, тот факт, что вы получаете сообщение об ошибке, в котором указывается, что кодек ascii не может быть использован, говорит о том, что что-то не так с вашей кодировкой в ​​Unicode - он думает, что вы пытаетесь для кодирования значения 0xed , которое не может быть представлено в ASCII, но вы сказали, что пытаетесь представить его в Unicode.

Я недостаточно умен, чтобы понять, какая конкретная строка вызывает проблема - если вы отредактируете свой вопрос, чтобы сказать мне, какая строка вызывает это сообщение об ошибке, я мог бы помочь немного больше (я думаю, это либо this_row.append (s.cell_value (row, col)) или bcw.writerow (this_row) , но будем признательны, если вы подтвердите).

0
ответ дан 30 November 2019 в 07:39
поделиться

Похоже, есть две возможности. Во-первых, возможно, вы неправильно открыли выходной файл:

«Если csvfile является файловым объектом, он должен открываться с флагом 'b' на платформах, где это имеет значение». ( http://docs.python.org/library/csv.html#module-csv )

Если проблема не в этом, то другой вариант для вас - использовать codecs.EncodedFile (file , input [, output [, errors]]) в качестве оболочки для вывода вашего .csv:

http://docs.python.org/library/codecs.html#module-codecs

Это позволит вам иметь фильтр файловых объектов от входящего UTF16 до UTF8. Хотя оба они технически являются «юникодом», способ их кодирования сильно отличается.

Примерно так:

rbc = open('file.csv','w')
bc = codecs.EncodedFile(rbc, "UTF16", "UTF8")
bcw = csv.writer(bc,csv.excel)

может решить проблему за вас, если я правильно понял проблему,

0
ответ дан 30 November 2019 в 07:39
поделиться
Другие вопросы по тегам:

Похожие вопросы: