2016-05-24 6 views
0

まず、私はPythonのnewbyです。大学でそれを学ばなければならず、その効率性に夢中になりました。python cursesウィンドウを使用した後にWindowsプロンプトが応答しないのはなぜですか?

cursesウィンドウを使用した後にWindows 7のプロンプトが応答しなくなるという問題があります。 Windows 10ではうまく動作します。私はデフォルト設定でWin7端末を使用しています。私のコードでは、cursesウィンドウを作成して、2つの同時進行バーを表示し、それぞれファイルのダウンロードを行います。私はcursesウィンドウをこのウィンドウ内の進行状況バーを処理するFileDownloadクラス(ダウンロードごとに1つのクラスインスタンス)に渡すことでこれを実装しました。奇妙なことに、ダウンロードが完了してコントロールがプロンプトに戻ると、Windows 7ではキーボードが応答しなくなります。ウィンドウを使用した後にcurses.endwin()を呼び出すことによってこの問題を回避しましたが、これにより、スクリーンバッファーの下に表示されるプロンプトが表示され、cursesウィンドウが表示されなくなりました。

ここに私のコードです。どんなアイデアも大歓迎です。ありがとう!

# Skeleton version for simulations. 
# Downloads 2 files simultaneously and shows a progress bar for each. 
# Each file download is a FileDownload object that interacts with a 
# common curses window passed as an argument. 

import requests, math, threading, curses, datetime 


class FileDownload: 

    def __init__(self, y_pos, window, url): 
     # Y position of the progress bar in the download queue window. 
     self.__bar_pos = int(y_pos) 
     self.__progress_window = window 
     self.__download_url = url 
     # Status of the file download object. 
     self.__status = "queued" 
     t = threading.Thread(target=self.__file_downloader) 
     t.start() 

    # Downloads selected file and handles its progress bar. 
    def __file_downloader(self): 
     file = requests.get(self.__download_url, stream=True) 
     self.__status = "downloading" 
     self.__progress_window.addstr(self.__bar_pos + 1, 1, "0%" + " " * 60 + "100%") 
     size = int(file.headers.get('content-length')) 
     win_prompt = "Downloading " + format(size, ",d") + " Bytes:" 
     self.__progress_window.addstr(self.__bar_pos, 1, win_prompt) 

     file_name = str(datetime.datetime.now().strftime("%Y-%m-%d_%H.%M.%d")) 
     dump = open(file_name, "wb") 

     # Progress bar length. 
     bar_space = 58 
     # Same as an index. 
     current_iteration = 0 
     # Beginning position of the progress bar. 
     progress_position = 4 
     # How many iterations will be needed (in chunks of 1 MB). 
     iterations = math.ceil(size/1024 ** 2) 

     # Downloads the file in 1MB chunks. 
     for block in file.iter_content(1024 ** 2): 
      dump.write(block) 

      # Progress bar controller. 
      current_iteration += 1 
      step = math.floor(bar_space/iterations) 
      if current_iteration > 1: 
       progress_position += step 
      if current_iteration == iterations: 
       step = bar_space - step * (current_iteration - 1) 
      # Updates the progress bar. 
      self.__progress_window.addstr(self.__bar_pos + 1, progress_position, 
              "#" * step) 
     dump.close() 
     self.__status = "downloaded" 

    # Returns the current status of the file download ("queued", "downloading" or 
    # "downloaded"). 
    def get_status(self): 
     return self.__status 


# Instantiates each file download. 
def files_downloader(): 

    # Creates curses window. 
    curses.initscr() 
    win = curses.newwin(8, 70) 
    win.border(0) 
    win.immedok(True) 

    # Download URLs. 
    urls = ["http://ipv4.download.thinkbroadband.com/10MB.zip", 
      "http://ipv4.download.thinkbroadband.com/5MB.zip"] 

    downloads_dct = {} 
    for n in range(len(urls)): 
     # Progress bar position in the window for the file. 
     y_pos = n * 4 + 1 
     downloads_dct[n + 1] = FileDownload(y_pos, win, urls[n]) 

    # Waits for all files to be downloaded before passing control of the terminal 
    # to the user. 
    all_downloaded = False 
    while not all_downloaded: 
     all_downloaded = True 
     for key, file_download in downloads_dct.items(): 
      if file_download.get_status() != "downloaded": 
       all_downloaded = False 

    # Prevents the prompt from returning inside the curses window. 
    win.addstr(7, 1, "-") 

    # This solves the unresponsive prompt issue but hides the curses window if the screen buffer 
    # is higher than the window size. 
    # curses.endwin() 

while input("\nEnter to continue: ") == "": 
    files_downloader() 
+0

Pythonの標準ライブラリは、Windows上で呪いを実装していません。あなたが使っているcursesのバージョンを人に伝えれば助けになるかもしれません。 – eryksun

+0

私はpython 3.5.1でcurses 2.2を使用しています。 – R01k

答えて

1

おそらく、あなたはcygwinの(とのncurses)を使用している:それは実行されている場合(他のcursesの実装など)ncursesベースの端末I/Oモードを変更します。あなたはおそらく見ている変化は

  • 入力文字が
  • をエコーされません あなたが入力行を終了するだけではなく、
  • 出力を入力する制御Jを入力する必要があるということです各行の末尾に自動的にフラッシュされない

これにより、1つの文字を読み取ることができるようになります。より効率的に端末を使用することができます。

に戻るを端末の通常の入出力モードに変更するには、endwin機能を使用します。 reset_shell_mode関数も便利です。

さらに読書:

+0

reset_shell_modeがトリックをしました。ありがとうございました! – R01k

関連する問題