Python shutil copyfile - 缺少最后几行

时间:2015-07-21 18:29:12

标签: python shutil file-copying

我经常错过使用shutil copyfile复制的文件的最后几个kb。

我做了一些研究,确实看到有人问过类似的事情: python shutil copy function missing last few lines

但我使用的是copyfile,它似乎使用了with语句......

with open(src, 'rb') as fsrc:
    with open(dst, 'wb') as fdst:
        copyfileobj(fsrc, fdst)

所以我很困惑,更多的用户没有这个问题,如果确实是某种缓冲问题 - 我会认为它更为人所知。

我非常简单地称复制文件,不要以为我可能做错了什么,基本上是按照我认为的标准方式做的:

copyfile(target_file_name,dest_file_name) 

然而,我每次都错过了最后4kb左右的文件。

我还没有触及在shutil中调用的copyfile函数,它是......

def copyfileobj(fsrc, fdst, length=16*1024):
    """copy data from file-like object fsrc to file-like object fdst"""
    while 1:
        buf = fsrc.read(length)
        if not buf:
            break
        fdst.write(buf)

所以我很茫然,但我想我即将学习关于冲洗,缓冲或with语句的内容,或者......帮助!感谢

到阿南德: Anand,我避免提及那些东西,因为我觉得它不是问题,但是因为你问...执行摘要是我从FTP抓取文件,检查文件是否是与上次保存副本时不同,如果是,则下载文件并保存副本。这是一个迂回的意大利面条代码,当我成为编码器的真正纯粹的功利新手时,我写道。它看起来像:

for filename in ftp.nlst(filematch):
    target_file_name = os.path.basename(filename)
    with open(target_file_name ,'wb') as fhandle:
    try:
        ftp.retrbinary('RETR %s' % filename, fhandle.write)
        the_files.append(target_file_name)
        mtime = modification_date(target_file_name)
        mtime_str_for_file = str(mtime)[0:10] + str(mtime)[11:13] + str(mtime)[14:16]    + str(mtime)[17:19] + str(mtime)[20:28]#2014-12-11 15:08:00.338415.
        sorted_xml_files = [file for file in glob.glob(os.path.join('\\\\Storage\\shared\\', '*.xml'))]
        sorted_xml_files.sort(key=os.path.getmtime)
        last_file = sorted_xml_files[-1]
        file_is_the_same = filecmp.cmp(target_file_name, last_file)
        if not file_is_the_same:
            print 'File changed!'
            copyfile(target_file_name, '\\\\Storage\\shared\\'+'datebreaks'+mtime_str_for_file+'.xml') 
        else:
            print 'File '+ last_file +' hasn\'t changed, doin nothin'
            continue

3 个答案:

答案 0 :(得分:4)

这里的问题很可能就是执行行 -

ftp.retrbinary('RETR %s' % filename, fhandle.write)

这是使用fhandle.write()函数将数据从ftp服务器写入文件(名称为target_file_name),但是在您调用时 - shutil.copyfile - fhandle的缓冲区尚未完全刷新,因此您在复制文件时错过了一些数据。

为确保不会发生这种情况,您可以将copyfile逻辑移出with的{​​{1}}块。

或者您可以在复制文件之前调用fhandle来刷新缓冲区。

我认为最好关闭文件(将逻辑移出fhandle.flush()块)。示例 -

with

答案 1 :(得分:2)

您正在尝试复制未关闭的文件。这就是为什么缓冲区没有刷新的原因。将copyfileobj移出with块,以允许fhandle关闭。

执行:

with open(target_file_name ,'wb') as fhandle:
    ftp.retrbinary('RETR %s' % filename, fhandle.write)

# and here the rest of your code
# so fhandle is closed, and file is stored completely on the disk

答案 2 :(得分:1)

This看起来有更好的方法来嵌套withs

with open(src, 'rb') as fsrc, open(dst, 'wb') as fdst:
        copyfileobj(fsrc, fdst)

我会尝试更像这样的东西。我远非专家,希望知识渊博的人可以提供一些见解。我最好的想法是内部with在外部{{1}}之前关闭。