如何确定文件是以二进制还是文本模式打开?

时间:2017-06-16 08:49:36

标签: python

给定一个文件对象,如何确定它是以字节模式打开(read返回bytes)还是以文本模式打开(read返回str)?它应该与阅读和写作一起工作。

换句话说:

>>> with open('filename', 'rb') as f:
...     is_binary(f)
...
True

>>> with open('filename', 'r') as f:
...     is_binary(f)
...
False

Another question听起来不相关。那个问题是关于猜测某个文件是否为二进制文件而不是内容。)

3 个答案:

答案 0 :(得分:14)

文件对象有.mode attribute

def is_binary(f):
    return 'b' in f.mode

这限制了对文件的测试;内存文件对象(如TextIOBytesIO)没有该属性。您还可以测试appropriate abstract base classes

import io

def is_binary(f):
    return isinstance(f, (io.RawIOBase, io.BufferedIOBase))

或反向

def is_binary(f):
    return not isinstance(f, io.TextIOBase)

答案 1 :(得分:0)

对于作为阅读打开的流,确定其模式的最可靠方法可能是从读取

def is_binary(f):
    return isinstance(f.read(0), bytes)

通过它确实有一个警告,如果流已经关闭(它可能会引发IOError)它将无法工作它会可靠地确定任何自定义文件类对象的二进制性适当的io ABCs,也不提供mode属性。

如果只需要Python 3支持,那么在字节和文本之间有明确的区别的情况下,也可以确定可写流的文本/二进制模式:

def is_binary(f):
    read = getattr(f, 'read', None)
    if read is not None:
        try:
            data = read(0)
        except (TypeError, ValueError):
            pass # ValueError is also a superclass of io.UnsupportedOperation
        else:
            return isinstance(data, bytes)
    try:
        # alternatively, replace with empty text literal
        # and swap the following True and False.
        f.write(b'')
    except TypeError:
        return False
    return True

除非你经常测试一个流是否处于二进制模式(这是不必要的,因为流的二进制不应该在对象的生命周期内改变),我怀疑由于广泛使用而导致任何性能缺陷捕捉异常将是一个问题(你当然可以针对更有可能的路径进行优化)。

答案 2 :(得分:-3)

有一个名为mimetypes的库,其中guess_type返回返回值。返回值是一个元组(类型,编码),其中类型为None,如果类型无法猜测(缺失或未知后缀)或字符串形式'type /子类型'

import mimetypes
file= mimetypes.guess_type(file)