通常我使用with语句在Python中处理文件,就像在这个块中通过HTTP下载资源一样:
with (open(filename), "wb"):
for chunk in request.iter_content(chunk_size=1024):
if chunk:
file.write(chunk)
file.flush()
Run Code Online (Sandbox Code Playgroud)
但这假设我知道文件名.假设我想使用tempfile.mkstemp().此函数返回打开文件和路径名的句柄,因此open在with语句中使用将是错误的.
我搜索了一下,发现了很多关于小心使用的警告mkstemp.一些博客文章几乎喊出来,当他们说不要扔掉返回的整数mkstemp.有关os级文件句柄与Python级文件对象不同的讨论.这没关系,但我找不到最简单的编码模式来确保这一点
mkstemp 被调用来获取要写入的文件with(open...模式获得的行为.所以我的问题是,在Python中有一种很好的方式来创建和写入mkstemp生成的文件,可能使用不同类型的状态,或者我必须手动执行类似fdopen或close等等.似乎应该有一个明确的这种模式.
aba*_*ert 11
在最简单的这种编码模式try:/ finally::
fd, pathname = tempfile.mkstemp()
try:
dostuff(fd)
finally:
os.close(fd)
Run Code Online (Sandbox Code Playgroud)
但是,如果您不止一次这样做,将它包装在上下文管理器中是微不足道的:
@contextlib.contextmanager
def mkstemping(*args):
fd, pathname = tempfile.mkstemp(*args)
try:
yield fd
finally:
os.close(fd)
Run Code Online (Sandbox Code Playgroud)
然后你可以这样做:
with mkstemping() as fd:
dostuff(fd)
Run Code Online (Sandbox Code Playgroud)
当然,如果你真的想要,你总是可以将fd包装在一个文件对象中(通过传递给它open,或者os.fdopen在旧版本中).但是......为什么要去额外的麻烦?如果你想要一个fd,请将它用作fd.
如果你不想要一个fd,除非你有充分的理由需要mkstemp而不是更简单和更高级别NamedTemporaryFile,你不应该使用低级API.这样做:
with tempfile.NamedTemporaryFile(delete=False) as f:
dostuff(f)
Run Code Online (Sandbox Code Playgroud)
除了更简单之外with,它还具有以下优点:它已经是Python文件对象而不仅仅是OS文件描述符(并且在Python 3.x中,它可以是Unicode文本文件).
更简单的解决方案是完全避免使用tempfile.
几乎所有的XML解析器都有办法解析字符串而不是文件.有了cElementTree,这只是呼唤fromstring而不是parse.所以,而不是这个:
req = requests.get(url)
with tempfile.NamedTemporaryFile() as f:
f.write(req.content)
f.seek(0)
tree = ET.parse(f)
Run Code Online (Sandbox Code Playgroud)
......这样做:
req = requests.get(url)
tree = ET.fromstring(req.content)
Run Code Online (Sandbox Code Playgroud)
当然第一个版本只需要将XML文档和解析后的树一个接一个地保存在内存中,而第二个版本需要同时保存它们,这样可能会使峰值内存使用量增加约30%.但这很少成为问题.
如果它是一个问题,很多XML库有办法在数据饲料,因为它到来时,许多下载库有办法通过将数据流比特位,正如你可能想象,这是一次真正的cElementTree的XMLParser和requests在几种不同的方式.例如:
req = requests.get(url, stream=True)
parser = ET.XMLParser()
for chunk in iter(lambda: req.raw.read(8192), ''):
parser.feed(chunk)
tree = parser.close()
Run Code Online (Sandbox Code Playgroud)
不仅仅是使用简单fromstring......但它仍然比使用临时文件更简单,并且可能更有效地启动.
如果使用双参数形式iter会让你感到困惑(很多人一开始很难理解它),你可以将其重写为:
req = requests.get(url, stream=True)
parser = ET.XMLParser()
while True:
chunk = req.raw.read(8192)
if not chunk:
break
parser.feed(chunk)
tree = parser.close()
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1691 次 |
| 最近记录: |