【问题标题】:How do I determine an open file's size in Python?如何在 Python 中确定打开文件的大小?
【发布时间】:2010-12-24 10:52:09
【问题描述】:

我想确保一个文件不会超过 2 GB(因为它必须在使用 ext 2 的系统上运行)。什么是检查文件大小的好方法,记住我将在两次检查之间写入这个文件?特别是,我是否需要担心尚未写入磁盘的缓冲、未刷新的更改?

【问题讨论】:

  • 您是否有理由不能自己跟踪文件大小 - 即在打开文件时查看文件大小并在写入时增加计数器?不是特别优雅,但它应该可以工作。
  • 我想这是我没有想到的可能性......我也可以试试。
  • 这不是低效吗?
  • ext2 下的最大文件大小限制为 16GiB -- 64TiB,具体取决于块大小。见en.wikipedia.org/wiki/Ext2。这并不能回答您的问题,只是认为这可能会有所帮助。
  • Jason,如果你让文件变得太大会怎样?通常在 Python 中,尽量不要“三思而后行”……让异常发生,然后处理它们。通常更快更清洁。如果您的柜台说文件即将变得太大,您会怎么做?当异常确实变得太大时,你能在捕获异常后做同样的事情吗?一些额外的细节可能会对您的问题有所帮助。

标签: python linux file filesystems ext2


【解决方案1】:

也许不是你想要的,但我还是会建议。

import os
a = os.path.getsize("C:/TestFolder/Input/1.avi")

对于打开的文件,您也可以使用fstat 函数,该函数可用于打开的文件。它需要一个整数文件句柄,而不是文件对象,所以你必须在文件对象上使用 fileno 方法:

a = open("C:/TestFolder/Input/1.avi")
b = os.fstat(a.fileno()).st_size

【讨论】:

    【解决方案2】:

    最可靠的方法是创建一个包装类,它会在您打开文件时检查文件的大小、跟踪写入和查找操作、根据这些操作计算当前大小并防止超出大小限制。

    【讨论】:

      【解决方案3】:

      或者,如果文件已经打开:

      >>> fsock = open('/etc/hosts', 'rb').read()
      >>> len(fsock)
      444
      

      这是文件的字节数。

      【讨论】:

        【解决方案4】:

        os.fstat(file_obj.fileno()).st_size 应该可以解决问题。我认为它会返回写入的字节。如果您担心缓冲,您可以随时进行刷新。

        【讨论】:

        • 也可以在附加模式下工作!谢谢你。是的,在调用这个之前我会冲洗。
        【解决方案5】:

        我不熟悉python,但是流对象(或打开文件时得到的任何东西)没有包含流当前位置的属性吗?

        类似于使用 ftell() C 函数或 .NET 中的 Stream.Position 获得的结果。

        显然,这仅在您位于流的末尾时才有效,如果您当前正在写入流的末尾。

        这种方法的好处是您不必关闭文件或担心未刷新的数据。

        【讨论】:

        • 'filehandle.tell()' 确实显示了打开文件中的字节数,并且可以在写入或附加模式下工作。不知道为什么所有这些更复杂的答案都得到了赞成。
        • @hurfdurf 不,f.tell() 在附加模式下似乎不能可靠地工作。除非你先f.seek(0,2)。我不知道为什么。
        【解决方案6】:

        你可以这样开始:

        class TrackedFile(file):
            def __init__(self, filename, mode):
                self.size = 0
                super(TrackedFile, self).__init__(filename, mode)
            def write(self, s):
                self.size += len(s)
                super(TrackedFile, self).write(s)
        

        那么你可以这样使用它:

        >>> f = TrackedFile('palindrome.txt', 'w')
        >>> f.size
        0
        >>> f.write('A man a plan a canal ')
        >>> f.size
        21
        >>> f.write('Panama')
        27
        

        显然,如果您不从头开始编写文件,则此实现不起作用,但您可以调整您的 __init__ 方法来处理初始数据。您可能还需要覆盖其他一些方法:例如,writelines

        这与编码无关,因为字符串只是字节序列。

        >>> f2 = TrackedFile('palindrome-latin1.txt', 'w')
        >>> f2.write(u'A man a plan a canál '.encode('latin1')
        >>> f3 = TrackedFile('palindrome-utf8.txt', 'w')
        >>> f3.write(u'A man a plan a canál '.encode('utf-8'))
        >>> f2.size
        21
        >>> f3.size
        22
        

        【讨论】:

        • 实际上并非如此。如果您使用 ASCII、ISO1559 和 UTF-8,结果将是相同的,但磁盘大小将不同。
        • 没有。如果您使用实际的字符串,它也适用于其他编码。修改答案以进行演示。
        • 诀窍是你不能只写 unicode 对象并依赖操作系统的编码。
        【解决方案7】:

        虽然这是一个老问题,但我认为 Isak 有最简单的解决方案。下面是如何在 Python 中执行此操作:

        # Assuming f is an open file
        >>> pos = f.tell()  # Save the current position
        >>> f.seek(0, 2)  # Seek to the end of the file
        >>> length = f.tell()  # The current position is the length
        >>> f.seek(pos)  # Return to the saved position
        >>> print length
        1024
        

        【讨论】:

        • 我认为在第一行(保存当前位置),您应该使用 f.tell(),而不是 seek(),这会导致异常,因为 seek() 至少需要 1 个参数.
        • @Jkm 是的,你是对的!不知道我是怎么错过的。谢谢!
        • 这将正确计算文件大小,但由于tell in append mode 的已知问题而无法正确恢复位置。
        • @personal_cloud 我认为只要您不在tellseek 之间写信,这不会是一个问题,但我可能错了。我的测试没有问题,但看起来这些问题因平台而异。感谢您指出这一点。
        猜你喜欢
        • 1970-01-01
        • 2020-09-26
        • 1970-01-01
        • 2011-10-31
        • 1970-01-01
        • 2015-08-15
        • 1970-01-01
        • 2011-10-18
        • 2010-11-10
        相关资源
        最近更新 更多