Ошибка, связанная с декодированием при объединении панд и шутиля - PullRequest
3 голосов
/ 29 мая 2019

Я пытаюсь скопировать несколько каталогов с помощью shutil.copytree и pandas (применить функцию). При проверке журнала я заметил, что некоторые файлы не могут быть скопированы из-за следующей ошибки: [Errno 2] Нет такого файла или каталога: PATH. Несмотря на то, что путь был верным. При дальнейшей проверке оказалось, что символ changed был изменен в \ xb4, что объясняет, почему файл не может быть найден.

Я пытался следовать советам в этом посте: Pandas преобразовывает столбец объекта в str - столбец содержит Unicode, float и т. Д. пытаясь преобразовать столбец в Unicode. Однако это приводит к следующей ошибке: UnicodeDecodeError: кодек «ascii» не может декодировать байт 0xcc в позиции 20: порядковый номер не в диапазоне (128)

import pandas as pd
import shutil

def copy_files(row):
    try:
        shutil.copy(row['1'], row['2'])
        return 'DONE'
    except Exception as e:
        return str(e)

df = pd.DataFrame({'1':['Y:\project\Test\1\RAÍ.pdf'],'2': 
['Y:\project\Test\2\RAÍ.pdf']})

df['errors'] = df.apply(copy_files, axis=1)

print(df['errors'][0])

Я ожидал, что будет напечатана строка 'DONE', но вместо этого я получил сообщение об ошибке:

[Errno 2] Нет такого файла или каталога: 'Y: \ project \ Test \ x01 \ RAI \ xcc \ x81.pdf'

EDIT:

Если использовать необработанные строковые литералы, например, так:

df = pd.DataFrame({r'1':[r'Y:\project\Test\1'],
              '2':[r'Y:\project\Test\2']})

def copy_files(row):
    try:
        shutil.copytree(row['1'], row['2'])
        return 'DONE'
    except Exception as e:
        return str(e)

df['errors'] = df.apply(copy_files, axis=1)

print(df['errors'][0])

Я все еще получаю следующий результат:

[( 'Y: \ Проект \ Test \ 1 \ RAI \ xb4i.pdf', 'Y: \ project \ Test \ 2 \ RAI \ xb4i.pdf', "[Errno 2] Нет такого файла или каталог: 'Y: \\ project \\ Test \\ 1 \\ RAI \ xb4i.pdf' ")]

1 Ответ

1 голос
/ 29 мая 2019

Где вы взяли этих персонажей?Похоже, что ваше имя содержит «LATIN CAPITAL LETTER I WITH ACUTE».Проблема в том, что UNICODE (независимо от кодировки) допускает более одного представления.Это может быть (обычная форма C или каноническая композиция) U + 00CD или '\xcd' или (нормальная форма D или каноническая декомпозиция) U + 0049 с последующим U + 0301 или 'I\u0301'.Эта форма NFD читается как LATIN CAPITAL LETTER I, за которой следует КОМБИНИРОВАНИЕ ОСТРОГО АКЦЕНТА.

Невозможно различить эти 2 формы на печатных или отображаемых символах, но, к сожалению, они являются разными строками как для Python, так и для файловой системы..

Как исправить: избегайте не ascii символов в именах файлов.Теперь вы знаете, почему ...

Обходные пути:

  1. Ваш источник содержит форму NFD.Вполне вероятно, что файловая система содержит форму NFC, поэтому вы можете попробовать:

    df = pd.DataFrame({'1':['Y:\project\Test\1\RAI\xcd.pdf'],'2': 
    ['Y:\project\Test\2\RAI\xcd.pdf']})
    
  2. Пуленепробиваемый способ - спросить файловую систему, какая строка на самом деле является именем файла:

    l = glob.glob('Y:\project\Test\1\RAI*.pdf')
    for name in l:
        print(name, [hex(ord(i)) for i in name])
    

    (обратите внимание на *, а не ?, потому что в форме NFD один глиф может соответствовать более чем одному символу). Это приведет к сбросу кодовых точек Юникода всех символов, известных файловой системе.При условии, что позже вы используете точно такое же представление, все должно работать нормально.


Refences:

...