2009-06-10 16 views
11

Tôi đang cố gắng tìm ra cách chuyển hướng đầu ra từ một số mã FORTRAN mà tôi đã tạo ra một giao diện Python bằng cách sử dụng F2PY. Tôi đã thử:Chuyển hướng FORTRAN (được gọi qua F2PY) đầu ra bằng 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 

Đây là phương pháp thực tế chuyển hướng đầu ra bằng Python, nhưng nó dường như không làm việc trong trường hợp này (ví dụ, đầu ra sẽ được hiển thị anyway).

Tôi đã tìm thấy a mailing list post from 2002 nói rằng "Có thể đọc tin nhắn từ các thiết bị pts, ví dụ: ttysnoop thực hiện việc này". Thông tin về ttysnoop có vẻ khá khó tìm thấy trực tuyến (tôi không nghĩ rằng nó được cập nhật trong vài năm tới, ví dụ: the first result on Google for "ttysnoop" chỉ có liên kết chết đến tarball, RPM và .deb) và this request for a port to OS X đã nhận được phản hồi " Không may mắn, nó đòi hỏi một số chức năng utmp linux cụ thể mà tôi không thể tạo ra. "

Tôi đang mở cho bất kỳ đề xuất nào về cách chuyển hướng đầu ra (nó không phải sử dụng ttysnoop).

Cảm ơn!

+1

Bạn có chắc chắn sản lượng fortran sẽ không thiết bị lỗi chuẩn thay vì stdout? –

+0

Vâng, tôi cũng đã thử chuyển hướng nó, và có kết quả tương tự. – srunni

Trả lời

17

Các fdin và stdout fds đang được kế thừa bởi thư viện được chia sẻ 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

Điều này sẽ ngăn chặn stderr là tốt? Nếu không, làm thế nào có thể được thực hiện? – srunni

+0

@aberration: dunno, bạn đã thử nghiệm nó với bất kỳ chương trình fortran nào viết thư cho stderr? – nosklo

+0

Tôi đã thử nó, và nó dường như hiển thị văn bản được viết cho stderr. – srunni

4

Dưới đây là một context manager mà tôi vừa viết kịch bản và thấy hữu ích, bởi vì tôi đã có một vấn đề tương tự với distutils.ccompiler.CCompiler.has_function khi làm việc trên pymssql. Tôi cũng sử dụng phương pháp mô tả tập tin nhưng tôi đã sử dụng context manager. Dưới đây là những gì tôi đã đưa ra:

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() 

Ngữ cảnh tại sao tôi tạo điều này là this blog post. Tương tự như bạn nghĩ.

tôi sử dụng nó như thế này trong một setup.py:

with stdchannel_redirected(sys.stderr, os.devnull): 
    if compiler.has_function('clock_gettime', libraries=['rt']): 
     libraries.append('rt') 
Các vấn đề liên quan