Freqüentemente, preciso enviar dados para o arquivo ou, se o arquivo não for especificado, para o stdout. Eu uso o seguinte snippet:
if target:
with open(target, 'w') as h:
h.write(content)
else:
sys.stdout.write(content)
Gostaria de reescrevê-lo e lidar com os dois alvos de maneira uniforme.
No caso ideal, seria:
with open(target, 'w') as h:
h.write(content)
mas isso não funcionará bem porque sys.stdout é fechado ao sair do with
bloco e eu não quero isso. Eu nem quero
stdout = open(target, 'w')
...
porque eu precisaria me lembrar de restaurar o stdout original.
Relacionado:
- Redirecionar stdout para um arquivo em Python?
- Manipulando exceções - artigo interessante sobre como lidar com exceções em Python, em comparação com C ++
Editar
Eu sei que posso encapsular target
, definir funções separadas ou usar o gerenciador de contexto . Procuro uma solução simples, elegante e idiomática que não exija mais do que 5 linhas
Respostas:
Apenas pensando fora da caixa aqui, que tal um
open()
método personalizado ?Use-o assim:
fonte
Fique com seu código atual. É simples e você pode dizer exatamente o que está fazendo apenas olhando para ele.
Outra maneira seria com um embutido
if
:Mas isso não é muito mais curto do que o que você tem e parece provavelmente pior.
Você também pode tornar
sys.stdout
impossível fechar, mas isso não parece muito pitônico:fonte
with unclosable(sys.stdout): ...
configurandosys.stdout.close = lambda: None
dentro deste gerenciador de contexto e reconfigurando-o para o valor antigo depois. Mas isso parece um pouco exagerado ...Por que LBYL quando você pode EAFP?
Por que reescrevê-lo para usar o bloco
with
/as
uniformemente quando você precisa fazê-lo funcionar de uma maneira complicada? Você adicionará mais linhas e reduzirá o desempenho.fonte
for
loop do Python termina capturando um erro StopIteration lançado pelo iterador que está percorrendo o loop, eu diria que o uso de exceções para controle de fluxo é totalmente Pythônico.target
éNone
quando sys.stdout se destina, você precisa pegarTypeError
em vez deIOError
.Outra solução possível: não tente evitar o método de saída do gerenciador de contexto, apenas duplique o stdout.
fonte
Uma melhoria da resposta de Wolph
Isso permite E / S binária e passa eventuais argumentos estranhos para
open
sefilename
realmente for um nome de arquivo.fonte
Eu também escolheria uma função de wrapper simples, que pode ser muito simples se você puder ignorar o modo (e, consequentemente, stdin x stdout), por exemplo:
fonte
ValueError: I/O operation on closed file
se tento gravar no arquivo fora dowith open_or_stdout(..)
bloco. o que estou perdendo? sys.stdout não deve ser fechado.Ok, se estamos entrando em guerras de uma linha, aqui está:
Gosto do exemplo original de Jacob, contanto que o contexto seja escrito apenas em um lugar. Seria um problema se você acabasse reabrindo o arquivo para muitas gravações. Acho que só tomaria a decisão uma vez no início do script e deixaria o sistema fechar o arquivo ao sair:
Você pode incluir seu próprio manipulador de saída se achar que é mais organizado
fonte
__del__
fariam isso.Se você realmente deve insistir em algo mais "elegante", ou seja, uma linha:
foo.txt
aparece e contém o textofoo
.fonte
Que tal abrir um novo fd para sys.stdout? Desta forma, você não terá problemas para fechá-lo:
fonte
./script.py >> file
sobrescrever o arquivo em vez de anexar a ele.Melhora leve em alguns casos.
fonte
Apenas duas linhas extras se você estiver usando Python 3.3 ou superior: uma linha para o extra
import
e uma linha para ostack.enter_context
.fonte