使用shutil复制中断在csv数据上循环

时间:2019-06-24 16:01:25

标签: python python-3.x csv shutil

我正在设置一个脚本,该脚本从名为{number} .jpg的文件夹中获取.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

(文件很多,但这是一个完整示例)

每个数字都将与这些范围中的每个范围进行比较,并放置在相应的文件夹中。如果仅打印目标文件和目标,则一切正常,结果如预期。但是,如果我尝试使用任何常规复制功能(copy,copyfile,copy2),循环就会中断。

文件结构如下:
数据
|-培训
|-压缩(CPR)
| --- COMPRESSION(CPR).csv
| ---图像数据将流向何处
|-更多文件夹..
|-验证
|-与培训相同
|-测试
|-与培训相同

这是Python3。我正在Ubuntu(Pop!OS)计算机上运行VS Code。我已经尝试了每种适合这种情况的shutil复制函数(copycopy2copyfile)。我尝试过复制到其他文件夹,并且可以。如果我将文件复制到父文件夹(即上述层次结构中的Training),而不是子目录,则可以正常工作。但是,出于标记目的,我需要在子目录中使用它们。

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值没有任何结果。我重构了代码,在该代码中我首先创建了文件夹和文件名的文本文件,然后读取该文件并复制了这些文件。效果很好。

谢谢您的帮助!

1 个答案:

答案 0 :(得分:0)

我认为副本没有问题。从错误消息中看,似乎正在读取CSV文件中的NULL字节。编写一些打印语句并观察该文件。

您可能会发现这很有帮助。 "Line contains NULL byte" in CSV reader (Python)