Python-ValueError:I/O操作在关闭的文件上-traceroute脚本+;印刷

Python-ValueError:I/O操作在关闭的文件上-traceroute脚本+;印刷,python,Python,当我在这里查找问题时,我看到过几次提到这个错误,但大多数似乎与打开和关闭文件有关 我复制了这个traceroute脚本,并在其中添加了一个argparse。我还想在它作为cron运行并记录到文件时添加一个打印。我想在日志文件中加一个时间戳。因此,我在底部添加了打印,现在得到一个错误 #!/usr/bin/python import socket import struct import sys import argparse import datetime # We want unbuffe

当我在这里查找问题时,我看到过几次提到这个错误,但大多数似乎与打开和关闭文件有关

我复制了这个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
回溯(最近一次呼叫最后一次):
文件“traceroute.py”,第83行,在
打印“跟踪在:{0}完成”。格式(datetime.datetime.now().strftime(“%d-%m-%Y%H:%m:%S”))
ValueError:对关闭的文件执行I/O操作

问题似乎在于脚本顶部附近的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