Использование shutil копирования разрывов цикла по данным CSV - PullRequest
1 голос
/ 24 июня 2019

Я устанавливаю скрипт, который берет изображения .jpg из папки с именем {number} .jpg и сравнивает это число, умноженное на частоту кадров, с диапазоном, заданным в файле csv. Затем jpg копируется в ту же папку, что и файл csv, содержащий диапазон, в который он помещается.

Таким образом, данные CSV выглядят так:

477.01645354635303,1087.1628371628808
1191.5980219780615,1777.622457542435
1915.5956043956126,2525.6515684316387
2687.7457042956867,3299.803336663285
3429.317892107908,4053.6603896103848
4209.835924075932,4809.700129870082

(файлов много, но это один полный пример)

Каждое число будет сравниваться с каждым из этих диапазонов и помещаться в соответствующую папку. Если я просто распечатываю целевой файл и место назначения, все работает нормально, и результаты ожидаются. Но если я попытаюсь использовать любую из функций копирования shutil (copy, copyfile, copy2), цикл будет прерван.

Структура файла выглядит так:
Данные
| -Дрессировка
| - КОМПРЕССИЯ (СЛР)
| --- СЖАТИЕ (CPR) .csv
| --- Где данные изображения будут идти
| --Больше папок ..
| -Validation
| --Так как Тренинг
| -Тест
| --Так как Тренинг

Это Python 3. Я запускаю VS Code на машине с Ubuntu (Pop! OS). Я пробовал каждую из shutil функций копирования, которые подходят для этого случая (copy, copy2, copyfile). Я пробовал копировать в разные папки, и это работает. Если я копирую файлы в родительскую папку (т. Е. Обучение в вышеупомянутой иерархии), а не в подкаталоги, он работает нормально. Однако они нужны мне в подкаталоге для целей маркировки.

for cur in file_list:
    with open(cur, 'r') as img:
        filename = ntpath.basename(cur)
        frame_num = int(filename[:-4]) # get number from filename
        frame_num = (frame_num - 1) * (30000./1001.) # it's one second from each frame in a video
        training = get_folders(train_path)
        for folder in training:
            train_csvfile = get_files(train_path + folder)
            if len(train_csvfile) > 0:
                with open(train_csvfile[0], 'r', encoding='latin-1', newline='') as source:
                    train_reader = csv.reader(source, delimiter = ',')
                    for trdata in train_reader:
                        if frame_num > float(trdata[0]) and frame_num < float(trdata[1]):
                            tr_path = os.path.join(train_path + folder, ntpath.basename(cur))
                            copy2(cur,tr_path)
                            print('Copied {} to training folder {}.'.format(filename, tr_path))

Код для получения файлов и папок:

def get_folders(a_dir):
    return [name for name in os.listdir(a_dir)
            if os.path.isdir(os.path.join(a_dir, name))]

def get_files(a_dir):
    a_dir = Path(a_dir)
    return [f for f in a_dir.glob('**/*') if f.is_file()]

file_list = get_files('/media/username/Seagate Expansion Drive/EXP 3/S1 C2/frames')

Полный вывод:

Copied 000017.jpg to training folder /home/username/Downloads/Event Data CSV/Data/Training/CPR (COMPRESSION)/000017.jpg.
Copied 000018.jpg to training folder /home/username/Downloads/Event Data CSV/Data/Training/CPR (COMPRESSION)/000018.jpg.
Copied 000019.jpg to training folder /home/username/Downloads/Event Data CSV/Data/Training/CPR (COMPRESSION)/000019.jpg.
Copied 000021.jpg to training folder /home/username/Downloads/Event Data CSV/Data/Training/CPR (COMPRESSION)/000021.jpg.
Traceback (most recent call last):
  File "tfinput.py", line 39, in <module>
    for trdata in train_reader:
_csv.Error: line contains NULL byte

Файлы правильно скопированы, как сказано (но ТОЛЬКО эти четыре из сотен)

Файлы csv в этом сценарии не изменяются вообще. Скрипт проходит через четыре изображения и вылетает с вышеуказанной ошибкой. Он правильно размещает эти четыре изображения. Если я попытаюсь снова запустить сценарий без регенерации данных, он сразу же вылетает. Однако, если я не использую функцию копирования, все работает нормально, и все правильные каталоги ввода и вывода приведены в моих инструкциях печати. Сценарий также может быть перезапущен без регенерации, когда нет оператора копирования. Это заставляет меня думать, что должна быть какая-то проблема с перезаписью, но так как я на самом деле не редактирую файлы csv, я не могу это указать.

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

РЕДАКТИРОВАТЬ: Я пошел вперед и распечатал весь файл, на котором он застрял. И кажется, что он читает первую строку, а затем вылетает. Я проверил это на другом файле и подтвердил, что он просто копирует файлы в первом диапазоне, а затем вылетает

РЕДАКТИРОВАТЬ 2: Я смог заставить это работать с помощью блока try-except в блоке, начиная с for trdata in train_reader:, однако он пропустил много записей

РЕДАКТИРОВАТЬ 3: Для любопытных я никогда не выяснял проблему, хотя подозреваю, что это была проблема перезаписи, так как проверка значений NULL без оператора copy ничего не дала. Я реорганизовал код, в котором я сначала создал текстовый файл с именем папки и имени файла, а затем прочитал этот файл и скопировал файлы. Это сработало идеально.

Спасибо за любую помощь !!

1 Ответ

0 голосов
/ 24 июня 2019

Не думаю, что это проблема с копией.Из сообщения об ошибке видно, что в читаемом файле CSV есть NULL-байт.Напишите несколько утверждений для печати и просмотрите этот файл.

Вы можете найти это полезным. «Строка содержит NULL байт» в программе чтения CSV (Python)

...