Quero redirecionar a impressão para um arquivo .txt usando python. Eu tenho um loop 'for', que 'imprimirá' a saída para cada um dos meus arquivos .bam enquanto eu quero redirecionar TODAS essas saídas para um arquivo. Então eu tentei colocar
f = open('output.txt','w'); sys.stdout = f
no começo do meu roteiro. No entanto, não recebo nada no arquivo .txt. Meu script é:
#!/usr/bin/python
import os,sys
import subprocess
import glob
from os import path
f = open('output.txt','w')
sys.stdout = f
path= '/home/xug/nearline/bamfiles'
bamfiles = glob.glob(path + '/*.bam')
for bamfile in bamfiles:
filename = bamfile.split('/')[-1]
print 'Filename:', filename
samtoolsin = subprocess.Popen(["/share/bin/samtools/samtools","view",bamfile],
stdout=subprocess.PIPE,bufsize=1)
linelist= samtoolsin.stdout.readlines()
print 'Readlines finished!'
........print....
........print....
Então qual é o problema? Alguma outra maneira além deste sys.stdout?
Eu preciso do meu resultado parecido com:
Filename: ERR001268.bam
Readlines finished!
Mean: 233
SD: 10
Interval is: (213, 252)
python
file-writing
LookIntoEast
fonte
fonte
f.write(data)
?f.write(line)
- insere uma quebra de linha no final.f.write(line)
não adiciona uma quebra de linha aos dados.f.write(line+'\n')
, no entanto ..Respostas:
A maneira mais óbvia de fazer isso seria imprimir em um objeto de arquivo:
No entanto, redirecionar o stdout também funciona para mim. Provavelmente é bom para um script único como este:
Redirecionar externamente a partir do próprio shell é outra boa opção:
Outras perguntas:
Qual é o primeiro nome do arquivo no seu script? Não o vejo inicializado.
Meu primeiro palpite é que a glob não encontra nenhum arquivo bamfiles e, portanto, o loop for não roda. Verifique se a pasta existe e imprima bamfiles no seu script.
Além disso, use os.path.join e os.path.basename para manipular caminhos e nomes de arquivos.
fonte
Você pode redirecionar a impressão com o
>>
operador.Na maioria dos casos, é melhor escrever o arquivo normalmente.
ou, se você tiver vários itens que deseja escrever com espaços no meio, como
print
:fonte
sys.stdout
, não que seja uma boa idéia.Como o objeto de arquivo normalmente contém o
write()
método, tudo o que você precisa fazer é passar um objeto de arquivo para seu argumento.Gravar / Substituir no Arquivo
Escrever / anexar ao arquivo
fonte
sys.stdout
:(Isso funciona perfeitamente:
Agora o hello será gravado no arquivo test.txt. Certifique-se de fechar
stdout
com umclose
, sem ele o conteúdo não será salvo no arquivofonte
sys.stdout.close()
, se você digitar algo no shell python, ele mostrará erro comoValueError: I/O operation on closed file.
imgur.com/a/xby9P . A melhor maneira de lidar com isso é seguir o que @Gringo Suave postouNão use
print
, uselogging
Você pode mudar
sys.stdout
para apontar para um arquivo, mas esta é uma maneira bastante complicada e inflexível de lidar com esse problema. Em vez de usarprint
, use ologging
móduloCom
logging
, você pode imprimir da mesma maneira que fariastdout
ou também pode gravar a saída em um arquivo. Você ainda pode usar os diferentes níveis de mensagens (critical
,error
,warning
,info
,debug
) para, por exemplo, só imprimir grandes questões para o console, mas ainda log ações código secundário em um arquivo.Um exemplo simples
Importe
logging
, obtenhalogger
e defina o nível de processamento:Se você deseja imprimir no stdout:
Se você também deseja gravar em um arquivo (se você deseja apenas gravar em um arquivo, pule a última seção):
Então, onde quer que você use,
print
use um doslogger
métodos:Para saber mais sobre o uso de
logging
recursos mais avançados , leia o excelentelogging
tutorial nos documentos do Python .fonte
A solução mais fácil não é através do python; é através da casca. Desde a primeira linha do seu arquivo (
#!/usr/bin/python
), suponho que você esteja em um sistema UNIX. Apenas useprint
instruções como normalmente faria e não abra o arquivo no seu script. Quando você executa o arquivo, em vez depara executar o arquivo, use
onde você substitui
<filename>
pelo nome do arquivo no qual deseja que a saída seja inserida. O>
token informa (a maioria) aos shells para definir stdout para o arquivo descrito pelo token a seguir.Uma coisa importante que precisa ser mencionada aqui é que "script.py" precisa ser tornado executável para
./script.py
ser executado.Portanto, antes de executar
./script.py
, execute este comandochmod a+x script.py
(torne o script executável para todos os usuários)fonte
print
para um arquivo. Seria razoável esperar que stdout (rastreios de pilha e similares) ainda imprima no terminal.Se você estiver usando Linux, sugiro que você use o
tee
comando A implementação é assim:Se você não quiser alterar nada no código, acho que essa pode ser a melhor solução possível. Você também pode implementar o logger, mas precisa fazer algumas alterações no código.
fonte
Você pode não gostar desta resposta, mas acho que é a CERTA. Não altere seu destino stdout, a menos que seja absolutamente necessário (talvez você esteja usando uma biblioteca que apenas gera saída para stdout ??? claramente não é o caso aqui).
Eu acho que é um bom hábito que você prepare seus dados com antecedência como uma string, depois abra seu arquivo e escreva tudo ao mesmo tempo. Isso ocorre porque as operações de entrada / saída são maiores quando você tem um identificador de arquivo aberto, maior a probabilidade de ocorrer um erro nesse arquivo (erro de bloqueio de arquivo, erro de E / S etc.). Apenas fazer tudo em uma operação não deixa dúvidas sobre quando pode ter dado errado.
Aqui está um exemplo:
E então, quando você terminar de coletar suas "linhas de dados" uma linha por item da lista, poderá juntá-las a alguns
'\n'
caracteres para tornar a saída da tabela completa; talvez até envolva sua instrução de saída em umwith
bloco, para segurança adicional (fechará automaticamente seu identificador de saída mesmo que algo dê errado):No entanto, se você tiver muitos dados para escrever, poderá escrevê-los um pedaço de cada vez. Não acho relevante para a sua aplicação, mas aqui está a alternativa:
fonte
Se o redirecionamento
stdout
funcionar para o seu problema, a resposta do Gringo Suave é uma boa demonstração de como fazê-lo.Para tornar ainda mais fácil , criei uma versão utilizando gerenciadores de contexto para uma sintaxe sucinta de chamada generalizada usando a
with
instrução:Para usá-lo, basta fazer o seguinte (derivado do exemplo de Suave):
É útil para redirecionar seletivamente
print
quando um módulo o usa de uma maneira que você não gosta. A única desvantagem (e esse é o desagradável para muitas situações) é que não funciona se alguém deseja vários encadeamentos com valores diferentes destdout
, mas isso requer um método melhor e mais generalizado: acesso indireto ao módulo. Você pode ver implementações disso em outras respostas a esta pergunta.fonte
Alterar o valor de sys.stdout altera o destino de todas as chamadas a serem impressas. Se você usar uma maneira alternativa de alterar o destino da impressão, obterá o mesmo resultado.
Seu bug está em outro lugar:
fonte
Algo para estender a função de impressão para loops
fonte
while
e não há necessidade de fechar o arquivo ao usar #with