接收文件对象或文件路径

时间:2014-08-05 19:35:51

标签: python

我知道在静态语言中,接收文件对象而不是表示路径的字符串(从软件设计角度来看)总是更好。但是,在像python这样的动态语言中,你看不到变量的类型,传递文件的“正确”方法是什么?

传递函数对象是不是有问题,因为你需要记住之后关闭它(你可能不会因为你看不到类型而没有)?

4 个答案:

答案 0 :(得分:2)

理想情况下,无论何时打开文件,您都会使用with语句,因此关闭将由此处理。

with open('filepath', 'r') as f:
    myfunc(f)

otherstuff() # f is now closed

来自documentation

  

最好在处理文件时使用with关键字   对象。这样做的好处是文件在之后正确关闭   它的套件即使在路上引发异常也会完成。

答案 1 :(得分:1)

  

然而,在像python这样的动态语言中你看不到   变量的类型,传递文件的“正确”方法是什么?

简短的回答是 - 你没有。

在大多数面向对象的语言中,有一个对象契约,它保证如果对象有一个方法quack,它就知道如何嘎嘎叫。有些语言在执行此合同(例如Java)和其他语言时非常严格。

最后,它归结为Python的一个原则EAFP

  

E a sk f orgiveness p ermission。这个常见的Python   编码风格假定存在有效的键或属性   如果假设被证明是假的,则捕获异常。这干净又快   风格的特点是存在许多尝试和除外   声明。该技术与许多人共同的LBYL风格形成鲜明对比   其他语言,如C.

LBYL =在你跳跃之前看看

这意味着如果您的方法需要一个“文件”(并在文档中说明这一点),假设您正在传递“类似对象的文件”。尝试对对象执行文件操作(如read()close()),然后在引发异常时捕获它。

EAFP方法的一个要点是,你可能会传递一个像文件一样工作的对象,换句话说 - 调用者知道他们在做什么。因此,如果您花时间检查确切的类型,那么您将拥有无法正常工作的代码。现在,呼叫者有责任满足您的“对象合同”;但是,如果他们不使用文件但使用内存缓冲区(与文件具有相同的方法)呢?或者是请求对象(同样,具有相同的文件类方法)。您无法检查代码中的所有这些变体。

这是首选方法 - 而不是LBYL方法,它首先进行类型检查。

因此,如果您的方法的文档声明它期望文件对象,它应该与任何“文件类似”的对象一起使用,但是当有人将字符串传递给文件路径时,您的方法应该引发适当的异常。

此外,更重要的是 - 您应该避免关闭方法中的对象;因为它可能不像前面解释过的“文件”。但是,如果您绝对必须,请确保您的方法的文档非常清楚地说明了这一点。

以下是一个例子:

def my_method(fobj):
    ''' Writes to fobj, which is any file-like object,
        and returns the object '''
    try:
        fobj.write('The answer is: {}\n'.format(42))
    except (AttributeError, TypeError):
        raise TypeError('Expected file-like object')
    return fobj

答案 2 :(得分:1)

像任何其他类型一样传递文件对象。

def f(myfile):
    myfile.write('asdf')

ofs = open(filepath, 'w') # ofs is file object
f(ofs) # passes file object
ofs.close()

也可以使用闭包。

def f():
    return open(filepath, 'w') # returns file object

ofs = f()
ofs.write('something')
ofs.close()

答案 3 :(得分:0)

您可以使用file objects in Python。当它们(自动)被垃圾收集时,文件将被关闭。

  

文件对象使用C的stdio包实现,可以使用内置的open()函数创建。