2016-11-17 12 views
1

このエラーは、クエストを参照するとここで数回述べられていますが、ほとんどはファイルの開閉に関係しているようです。Python - ValueError:閉じたファイルの入出力操作 - 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')) 

エラーエラーが表示されます。問題は、スクリプトsys.stdoutの上部付近にカスタムクラスに再割り当てされていることであるように

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は実際には同じではないので、印刷にはおそらく問題があります。

簡単な修正は、スクリプトの最後にprintの代わりに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

関連する問題