これの最も単純なコーディング パターンはtry:
/finally:
です。
fd, pathname = tempfile.mkstemp()
try:
dostuff(fd)
finally:
os.close(fd)
ただし、これを複数回行う場合は、コンテキスト マネージャーでラップするのは簡単です。
@contextlib.contextmanager
def mkstemping(*args):
fd, pathname = tempfile.mkstemp(*args)
try:
yield fd
finally:
os.close(fd)
そして、次のことができます:
with mkstemping() as fd:
dostuff(fd)
もちろん、本当に必要な場合は、いつでも fd をファイル オブジェクトにラップすることができます (open
またはos.fdopen
古いバージョンに渡すことにより)。しかし… なぜ余計な手間をかける必要があるのでしょうか? fd が必要な場合は、fd として使用します。
また、 fd が必要ないmkstemp
場合は、単純で高レベルの の代わりに必要な正当な理由がない限り、低レベル API を使用しないNamedTemporaryFile
でください。これを行うだけです:
with tempfile.NamedTemporaryFile(delete=False) as f:
dostuff(f)
より単純であることに加えてwith
、これは単なる OS ファイル記述子ではなく、すでに Python ファイル オブジェクトであるという利点もあります (Python 3.x では、Unicode テキスト ファイルにすることができます)。
さらに簡単な解決策は、一時ファイルを完全に回避することです。
ほとんどすべての XML パーサーには、ファイルではなく文字列を解析する方法があります。では、 の代わりにcElementTree
を呼び出すだけです。したがって、これの代わりに:fromstring
parse
req = requests.get(url)
with tempfile.NamedTemporaryFile() as f:
f.write(req.content)
f.seek(0)
tree = ET.parse(f)
…これを行うだけです:
req = requests.get(url)
tree = ET.fromstring(req.content)
もちろん、最初のバージョンでは XML ドキュメントと解析されたツリーをメモリ内に順番に保持するだけで済みますが、2 番目のバージョンでは両方を一度に保持する必要があるため、ピーク時のメモリ使用量が約 30% 増加する可能性があります。しかし、これが問題になることはめったにありません。
それがXMLParser
問題である場合、多くの XML ライブラリには、データが到着したときにデータをフィードする方法があり、多くのダウンロード ライブラリには、データをビットごと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()
…を使用するほど単純ではありませんfromstring
が、一時ファイルを使用するよりも単純であり、おそらく起動がより効率的です。
の 2 引数形式の使用に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()