如何在python中接受文件或路径作为方法的参数

2024-04-19 18:29:35 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在尝试编写一个方法,该方法将接受打开的文件

myFile = open("myFile.txt")
obj.writeTo(myFile)
myFile.close()

或者一个有路径的字符串

obj.writeTo("myFile.txt")

方法实现如下:

def writeTo(self, hessianFile):
    if isinstance(hessianFile,file):
        print("File type")
    elif isinstance(hessianFile,str):
        print("String type")
    else:
        pass

但这引起了一个错误

NameError: global name 'file' is not defined

为什么没有定义文件类型?文件不应该一直被定义吗?如何更正实现以正确地将文件的两个路径都作为有效的参数类型


Tags: 文件方法路径txtobjclose定义type
6条回答

Python 3中没有file类型。它在Python 2中是内置的,但在Python 3中消失了。比较以下内容:

Python 2.7.1 [...]
>>> f = open('zz.bak', 'w')
>>> type(f)
<type 'file'>
>>> print f.__doc__
file(name[, mode[, buffering]]) -> file object

Open a file.  The mode can be 'r', 'w' or 'a' for reading (default),
writing or appending.  The file will be created if it doesn't exist
when opened for writing or appending; it will be truncated when
opened for writing.  Add a 'b' to the mode for binary files.
Add a '+' to the mode to allow simultaneous reading and writing.
If the buffering argument is given, 0 means unbuffered, 1 means line
buffered, and larger numbers specify the buffer size.  The preferred way
to open a file is with the builtin open() function.
Add a 'U' to mode to open the file for input with universal newline
support.  Any line ending in the input file will be seen as a '\n'
in Python.  Also, a file so opened gains the attribute 'newlines';
the value for this attribute is one of None (no newline read yet),
'\r', '\n', '\r\n' or a tuple containing all the newline types seen.

'U' cannot be combined with 'w' or '+' mode.

在Python 3中。。。

Python 3.2.1 [...]
>>> f = open('xx', 'w')
>>> type(f)
<class '_io.TextIOWrapper'>
>>> print(f.__doc__)
Character and line based layer over a BufferedIOBase object, buffer.

encoding gives the name of the encoding that the stream will be
decoded or encoded with. It defaults to locale.getpreferredencoding.

errors determines the strictness of encoding and decoding (see the
codecs.register) and defaults to "strict".

newline can be None, '', '\n', '\r', or '\r\n'.  It controls the
handling of line endings. If it is None, universal newlines is
enabled.  With this enabled, on input, the lines endings '\n', '\r',
or '\r\n' are translated to '\n' before being returned to the
caller. Conversely, on output, '\n' is translated to the system
default line seperator, os.linesep. If newline is any other of its
legal values, that newline becomes the newline when the file is read
and it is returned untranslated. On output, '\n' is converted to the
newline.

If line_buffering is True, a call to flush is implied when a call to
write contains a newline character.

别打支票!不是Python。鸭子打字的核心是,如果它像鸭子一样呱呱叫,那它就是鸭子。您需要的行为是,如果它是类似于的文件,那么它可以工作;如果它是类似于的字符串,那么它可以工作。这不仅仅是意识形态上的——因为这是Python中的标准,人们希望能够给你一个类似文件的对象并让它工作。如果仅将其限制为特定的文件类型,则代码将脆弱且不灵活。

最简单的选择是简单地选择更常见的结果,并尝试按您的方式处理该结果,如果出现异常,则无法使用其他方法:

def writeTo(self, hessianFile):
    try:
        with open(hessianFile, "w") as f:
            do_stuff(f)
    except TypeError:
        do_stuff(hessianFile)

如果您习惯了“使用异常进行流控制”被认为是不好的其他语言,这可能看起来很糟糕,但在Python中却不是这样,因为它们是经常使用这种方式的语言的核心部分(每个for循环都以异常结束!)。

或者,如果您认为在大多数情况下更可能获得一个文件对象,请采用另一种方法:

def writeTo(self, hessianFile):
    try:
        do_stuff(f)
    except AttributeError:
        with open(hessianFile, "w") as f:
            do_stuff(f)

注意我使用的the ^{} statement这是处理打开文件的最好方法-它更可读,而且总是为您关闭文件,即使在出现异常时也是如此。

如果您发现您必须输入check(例如:即使操作失败,也没有短路的方法),那么您应该检查字符串端,因为它更容易确定是字符串类型的还是文件类型的。如果要检查类似的文件,则应该实现一个abstract base class,并查找所需的功能,而不是实际的类型检查。

原始代码失败的原因是file不是3.x中open()返回的对象的基类

The type of file object returned by the open() function depends on the mode. When open() is used to open a file in a text mode ('w', 'r', 'wt', 'rt', etc.), it returns a subclass of io.TextIOBase (specifically io.TextIOWrapper). When used to open a file in a binary mode with buffering, the returned class is a subclass of io.BufferedIOBase. The exact class varies: in read binary mode, it returns a io.BufferedReader; in write binary and append binary modes, it returns a io.BufferedWriter, and in read/write mode, it returns a io.BufferedRandom. When buffering is disabled, the raw stream, a subclass of io.RawIOBase, io.FileIO, is returned. Source

所以你需要^{}

不要使用名称“file”(python中的内置对象)作为类文件对象的名称。

f = open("myFile.txt")
obj.writeTo(f)
f.close()

示例:

>>> filetype = lambda x: isinstance(x, file)
>>> file = open('t','w')
>>> filetype(file)

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 1, in <lambda>
TypeError: isinstance() arg 2 must be a class, type, or tuple of classes and types

>>> f = open('t','w')
>>> del file
>>> filetype(f)
True

相关问题 更多 >