Python将lxml与fileinput一起使用
拥有一个简单的xmlPython将lxml与fileinput一起使用,python,file-io,lxml,Python,File Io,Lxml,拥有一个简单的xml <?xml version="1.0" encoding="UTF-8" ?> <root> <child>abc</child> </root> 然而,我尝试修改脚本,然后允许它从文件或stdin解析xml,但没有成功: fi = fileinput.input('tst.xml') for _, element in lxml.etree.iterparse(fi, tag='child'):
<?xml version="1.0" encoding="UTF-8" ?>
<root>
<child>abc</child>
</root>
然而,我尝试修改脚本,然后允许它从文件或stdin
解析xml,但没有成功:
fi = fileinput.input('tst.xml')
for _, element in lxml.etree.iterparse(fi, tag='child'):
print element.text
# File "iterparse.pxi", line 371, in lxml.etree.iterparse.__init__ (src/lxml/lxml.etree.c:97283)
# File "apihelpers.pxi", line 1411, in lxml.etree._encodeFilename (src/lxml/lxml.etree.c:22515)
# TypeError: Argument must be string or unicode.
我不确定我做错了什么。对象在python中不是类似文件的对象吗?您不应该尝试使用
fileinput
模块,而是直接这样做:
if filename == '-': # or, if we don't have a filename argument
f = sys.stdin
else:
f = open(filename, 'r')
在没有深入调查的情况下,出现异常的原因似乎是
FileInput
类没有提供read
方法。
为了实现我的目标,我现在开始写我自己的包装:
class FileInput(object):
def __init__(self, filename=None, *args, **kwargs):
self.file = open(filename, *args, **kwargs) if filename and filename != "-" else sys.stdin
def __enter__(self):
return self.file
def __exit__(self, type, value, traceback):
if self.file is not sys.stdin:
self.file.close()
def __getattr__(self, name):
return getattr(self.file, name)
不过我会等待一个更好的答案。也许
lxml.etree.iterparse()
只处理一个真实的文件,而不是任何类似文件的对象。这可能不是真的,因为sys.stdin
据说是一个类似文件的对象,在Python 2.x中,iterparse()
解析时没有任何问题,默认情况下,sys.stdin
是一个真正的文件对象——我的意思是它的type()
是file
。fileinput.input()的情况并非如此。请注意,后者有一个方法fileno()
,但它返回-1。我不确定使用返回-1的方法fileno()
的意义何在,因为任何C代码试图通过查询其文件描述符来使用类似文件的对象,都会在尝试使用-1时出错…但是。。为什么?您的方法没有提供正确的结束处理。如果f不是sys.stdin:f.close()
,而且它也不是异常安全的,那么我必须编写样板文件。您使用文件输入
也不能提供正确的关闭处理。。。事实上,fileinput
是一个非常古老的Python模块,因此它不能与with
语句结合使用。使用试试:最后:
怎么样?我同意这只是几行样板文件,但我不知道还有什么更简洁的解决方案,对不起。我尽可能简化了我的示例,它看起来像是以contextlib.closing(fileinput.input(args.input))作为输入:
在现实世界中,它提供了必要的异常安全性,并且工作正常,因为FileInput
的close()
方法检查了sys.stdin
而没有关闭它。无论如何,谢谢你的帮助。
class FileInput(object):
def __init__(self, filename=None, *args, **kwargs):
self.file = open(filename, *args, **kwargs) if filename and filename != "-" else sys.stdin
def __enter__(self):
return self.file
def __exit__(self, type, value, traceback):
if self.file is not sys.stdin:
self.file.close()
def __getattr__(self, name):
return getattr(self.file, name)