2017-01-12 47 views
-1

我發現下面的代碼在網上時,添加創建的列表,打印長度的嘗試「ValueError異常:在關閉的文件I/O操作」試圖打印列表

from __future__ import print_function 
import socket 
import struct 
import sys 
import os 
import webbrowser 
import json 
import urllib 

# 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_name): 
    dest_addr = socket.gethostbyname(dest_name) 
    port = 33434 
    max_hops = 30 
    icmp = socket.getprotobyname('icmp') 
    udp = socket.getprotobyname('udp') 
    ttl = 1 
    IPlist = [] 

    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_name, port)) 
     curr_addr = None 
     curr_name = None 
     finished = False 
     tries = 1 
     while not finished and tries > 0: 
      try: 
       _, curr_addr = recv_socket.recvfrom(512) 
       finished = True 
       curr_addr = curr_addr[0] 
      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: 
      IPlist.append(curr_addr) 
      print(len(IPlist)) 

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

if __name__ == "__main__": 
    main('google.com') 

這是示例代碼模擬traceroute的功能。

我試圖添加(通過使用append)所有存儲在curr_addr中的IP地址列表。我正在檢查該行列表的長度以確保它不斷增長。

我每次運行它,我得到這個錯誤:

1 Traceback (most recent call last): 
    File "traceroute.py", line 96, in <module> 
    main('google.com') 
    File "traceroute.py", line 84, in main 
    print(len(IPlist)) 
ValueError: I/O operation on closed file 

不要忽略上面的行號,因爲我已刪除了之前發佈的註釋代碼了。

+0

你爲什麼每次迭代循環都要打開/關閉套接字? –

+0

@JonathonReinhart部分代碼不是我的。我完全不理解它,並且正在慢慢嘗試。我唯一的代碼是列表並試圖獲取它的長度。也許我應該說,在主帖 –

+0

爲什麼你搞亂'sys.stdout'和'flushfile'的東西,而不是隻是添加'flush = True'到相關的print()調用? – TigerhawkT3

回答

0

這個問題與您的flushfile類不無關係。

問題是flushfile繼承自file,其closed屬性默認爲True。因此,當您嘗試print()sys.stdout時,它認爲sys.stdout已關閉。

您有幾種選擇:使用flushfile

  1. 停止。它壞了。如評論中所述,print() function採用可選flush參數。只是用它來代替:
print("This will be flushed even without a newline", end=None, flush=True) 
  • 更改flushfile基類從fileobject正如我所說的,file.closed屬性默認爲True,並且不能手動設置。根據經驗,如果您只想print()即可,sys.stdout只有write方法。
  • +0

    謝謝。這解決了我的問題。 –

    +0

    你選擇了哪個選項?我強烈建議選擇1.另外,請記住爲任何可幫助您的答案投票,並接受最能解決您問題的答案。 –

    +0

    我去了第一個選項。刪除flushfile類並用print()替換所有sys.stdout.write() –

    相關問題