2016-11-17 83 views
1

我看到這個錯誤提到了幾次,當我查看questiotns但大多數似乎與打開和關閉文件有關。Python - ValueError:關閉文件的I/O操作 - traceroute腳本+打印

我複製了這個traceroute腳本,並給它添加了一個argparse。我也想爲它添加一個打印,就像運行一個cron並記錄到一個文件一樣。我想在日誌文件中添加時間戳。因此,我加在底部的打印,現在得到一個錯誤

#!/usr/bin/python 

import socket 
import struct 
import sys 
import argparse 
import datetime 

# We want unbuffered stdout so we can provide live feedback for 
# each TTL. You could also use the "-u" flag to Python. 
class flushfile(file): 
    def __init__(self, f): 
     self.f = f 
    def write(self, x): 
     self.f.write(x) 
     self.f.flush() 

sys.stdout = flushfile(sys.stdout) 

def main(dest): 
    dest_addr = socket.gethostbyname(dest) 
    port = 33434 
    max_hops = 30 
    icmp = socket.getprotobyname('icmp') 
    udp = socket.getprotobyname('udp') 
    ttl = 1 
    while True: 
     recv_socket = socket.socket(socket.AF_INET, socket.SOCK_RAW, icmp) 
     send_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, udp) 
     send_socket.setsockopt(socket.SOL_IP, socket.IP_TTL, ttl) 

     # Build the GNU timeval struct (seconds, microseconds) 
     timeout = struct.pack("ll", 5, 0) 

     # Set the receive timeout so we behave more like regular traceroute 
     recv_socket.setsockopt(socket.SOL_SOCKET, socket.SO_RCVTIMEO, timeout) 

     recv_socket.bind(("", port)) 
     sys.stdout.write(" %d " % ttl) 
     send_socket.sendto("", (dest, port)) 
     curr_addr = None 
     curr_name = None 
     finished = False 
     tries = 3 
     while not finished and tries > 0: 
      try: 
       _, curr_addr = recv_socket.recvfrom(512) 
       finished = True 
       curr_addr = curr_addr[0] 
       try: 
        curr_name = socket.gethostbyaddr(curr_addr)[0] 
       except socket.error: 
        curr_name = curr_addr 
      except socket.error as (errno, errmsg): 
       tries = tries - 1 
       sys.stdout.write("* ") 

     send_socket.close() 
     recv_socket.close() 

     if not finished: 
      pass 

     if curr_addr is not None: 
      curr_host = "%s (%s)" % (curr_name, curr_addr) 
     else: 
      curr_host = "" 
     sys.stdout.write("%s\n" % (curr_host)) 

     ttl += 1 
     if curr_addr == dest_addr or ttl > max_hops: 
      break 

if __name__ == "__main__": 
    parser = argparse.ArgumentParser(description='Traceroute') 
    parser.add_argument('-H' '--dest', 
         dest='destination', 
         help='IP or Hostname', 
         required='True', 
         default='127.0.0.1') 
    parser_args = parser.parse_args() 
    main(parser_args.destination) 
    print 'Trace completed at:{0}'.format(datetime.datetime.now().strftime('%d-%m-%Y %H:%M:%S')) 

錯誤:

Traceback (most recent call last): 
    File "traceroute.py", line 83, in <module> 
    print 'Trace completed at:{0}'.format(datetime.datetime.now().strftime('%d-%m-%Y %H:%M:%S')) 
ValueError: I/O operation on closed file 

回答

2

它看起來像問題是,附近的腳本sys.stdout的頂部被重新分配給一個自定義類。打印可能有問題,因爲sys.stdout實際上不再是相同的。

一個簡單的解決方法是使用sys.stdout.write而不是在腳本末尾打印。

例如:

sys.stdout.write(
     'Trace completed {0}\n'. 
     format(datetime.datetime.now(). 
     strftime('%d-%m-%Y %H:%M:%S')) 
    ) 

另一種選擇是,以節省sys.stdout的原值和附近腳本的末尾恢復它,打印前:

old_sys_stdout = sys.stdout 
sys.stdout = flushfile(sys.stdout) 
... 
sys.stdout = old_sys_stdout 
#print as normal 
+0

完美,謝謝! – AlexW

相關問題