2009-06-10 8 views
11

Sto cercando di capire come reindirizzare l'output da un codice FORTRAN per il quale ho generato un'interfaccia Python utilizzando F2PY. Ho provato:Reindirizzamento dell'output FORTRAN (chiamato tramite F2PY) in Python

from fortran_code import fortran_function 
stdout_holder = sys.stdout 
stderr_holder = sys.stderr 
sys.stdout = file("/dev/null","w") 
fortran_function() 
sys.stdout.close() 
sys.stderr.close() 
sys.stdout = stdout_holder 
sys.stderr = stderr_holder 

questo è il metodo de facto di reindirizzare l'output in Python, ma non sembra funzionare in questo caso (vale a dire, l'output viene visualizzato in ogni caso).

Ho trovato a mailing list post from 2002 dicendo che "È possibile leggere messaggi da dispositivi pts, ad esempio ttysnoop fa questo". Le informazioni su ttysnoop sembrano essere piuttosto difficili da trovare online (non credo sia stato aggiornato in parecchi anni, ad esempio, the first result on Google for "ttysnoop" ha solo dead link a tarball, RPM e .deb), e this request for a port to OS X ha ricevuto la risposta " Nessuna fortuna, richiede alcune funzioni di utmp specifiche di Linux che non riesco a creare. "

Sono aperto a qualsiasi suggerimento su come reindirizzare l'output (non è necessario utilizzare ttysnoop).

Grazie!

+1

Sei sicuro l'uscita FORTRAN non sta per stderr invece di stdout? –

+0

Sì, ho appena provato a reindirizzarlo e ho ottenuto lo stesso risultato. – srunni

risposta

17

I file stdin e stdout vengono ereditati dalla libreria condivisa C.

from fortran_code import fortran_function 
import os 

print "will run fortran function!" 

# open 2 fds 
null_fds = [os.open(os.devnull, os.O_RDWR) for x in xrange(2)] 
# save the current file descriptors to a tuple 
save = os.dup(1), os.dup(2) 
# put /dev/null fds on 1 and 2 
os.dup2(null_fds[0], 1) 
os.dup2(null_fds[1], 2) 

# *** run the function *** 
fortran_function() 

# restore file descriptors so I can print the results 
os.dup2(save[0], 1) 
os.dup2(save[1], 2) 
# close the temporary fds 
os.close(null_fds[0]) 
os.close(null_fds[1]) 

print "done!" 
+0

Questo sopprimerà anche lo stderr? Se no, come può essere realizzato? – srunni

+0

@aberration: non so, l'hai provato con i programmi fortran che scrivono su stderr? – nosklo

+0

L'ho provato e sembra che mostri il testo scritto su stderr. – srunni

4

Ecco un context manager che ho recentemente scritto e l'ho trovato utile, perché ho avuto un problema simile con distutils.ccompiler.CCompiler.has_function mentre si lavora su pymssql. Ho anche usato l'approccio descrittore di file, ma ho usato uno context manager. Ecco quello che mi si avvicinò con:

import contextlib 


@contextlib.contextmanager 
def stdchannel_redirected(stdchannel, dest_filename): 
    """ 
    A context manager to temporarily redirect stdout or stderr 

    e.g.: 


    with stdchannel_redirected(sys.stderr, os.devnull): 
     if compiler.has_function('clock_gettime', libraries=['rt']): 
      libraries.append('rt') 
    """ 

    try: 
     oldstdchannel = os.dup(stdchannel.fileno()) 
     dest_file = open(dest_filename, 'w') 
     os.dup2(dest_file.fileno(), stdchannel.fileno()) 

     yield 
    finally: 
     if oldstdchannel is not None: 
      os.dup2(oldstdchannel, stdchannel.fileno()) 
     if dest_file is not None: 
      dest_file.close() 

Il contesto per il motivo per cui ho creato questo è a this blog post. Simile al tuo, penso.

lo uso come questo in un setup.py:

with stdchannel_redirected(sys.stderr, os.devnull): 
    if compiler.has_function('clock_gettime', libraries=['rt']): 
     libraries.append('rt') 
Problemi correlati