簡體   English   中英

管道輸入到 Python 程序,然后從用戶那里獲取輸入

[英]Pipe input to Python program and later get input from user

假設我想將輸入通過管道傳輸到 Python 程序,然后在命令行上從用戶那里獲取輸入。

echo http://example.com/image.jpg | python solve_captcha.py

solve_captcha.py的內容是:

import sys 
image_url = sys.stdin.readline()

# Download and open the captcha...

captcha = raw_input("Solve this captcha:")
# do some processing...

以上會EOFError: EOF when reading a line錯誤EOFError: EOF when reading a line觸發EOFError: EOF when reading a line

我還嘗試添加sys.stdin.close()行,這會提示ValueError: I/O operation on closed file

您可以將信息通過管道傳輸到stdin ,然后再從用戶那里獲得輸入嗎?

注意:這是一個精簡的、簡化的示例 - 請不要回答說“你為什么要在第一種情況下這樣做”,這真的很令人沮喪。 我只想知道您是否可以將信息通過管道傳輸到stdin ,然后再提示用戶輸入。

這個問題沒有通用的解決方案。 最好的資源似乎是這個郵件列表線程

基本上,管道到程序將程序的stdin連接到該管道,而不是終端。

郵件列表線程為 *nix 提供了幾個相對簡單的解決方案

打開 /dev/tty 替換 sys.stdin:

sys.stdin = open('/dev/tty')
a = raw_input('Prompt: ')

運行腳本時將 stdin 重定向到另一個文件句柄,並從中讀取:

sys.stdin = os.fdopen(3)
a = raw_input('Prompt: ')
$ (echo -n test | ./x.py) 3<&0

以及使用 curses建議 請注意,郵件列表線程很古老,因此您可能需要修改您選擇的解決方案。

bash 有進程替換,它創建一個 FIFO,你可以把它當作一個文件對待,而不是

echo http://example.com/image.jpg | python solve_captcha.py

您可以使用

python solve_capcha.py <(echo http://example.com/image.jpg)

您將作為文件打開 solve_capcha.py 的第一個參數,我認為 sys.stdin 仍可用於從鍵盤讀取輸入。

您可以關閉 stdin,然后重新打開它以讀取用戶輸入。

import sys, os

data = sys.stdin.readline()
print 'Input:', data
sys.stdin.close()
sys.stdin = os.fdopen(1)
captcha = raw_input("Solve this captcha:")
print 'Captcha', captcha

這樣做是為了模擬raw_input() ,因為我和你有同樣的問題。 整個stdinclear丑陋只是為了讓它看起來漂亮。 這樣您就可以看到您正在鍵入的內容。

def getInputFromKeyPress(promptStr=""):

    if(len(promptStr)>0):
        print promptStr
    """
    Gets input from keypress until enter is pressed
    """

    def clear(currStr):
        beeString, clr="",""

        for i in range(0,len(currStr)):
            clr=clr+" "
            beeString=beeString+"\b"

        stdout.write(beeString)
        stdout.write(clr)
        stdout.write(beeString)


    from msvcrt import kbhit, getch
    from sys import stdout
    resultString, userInput="", ""

    while(userInput!=13):
        if (kbhit()):
            charG=getch()
            userInput= ord(charG)

            if(userInput==8):#backspace
                resultString=resultString[:-1]
                clear(resultString)


            elif(userInput!=13):
                resultString="".join([resultString,charG])

            clear(resultString)
            stdout.write(resultString)

            if(userInput==13):
                clear(resultString)

    #print "\nResult:",resultString

    return resultString.strip()

我更新了@Bob 的答案以支持刪除、ctrl + [left, right, home, end] 按鍵並簡化了標准輸出的清除和重寫。

def keypress_input(prompt_str=""):
    """
    Gets input from keypress using `msvcrt` until enter is pressed.
    Tries to emulate raw_input() so that it can be used with piping.
    :param prompt_str: optional string to print before getting input
    :type prompt_str: str
    """
    from re import finditer
    from msvcrt import getch
    from sys import stdout

    # print even if empty to create new line so that previous line won't be overwritten if it exists
    print prompt_str

    user_input = ""
    curr_chars = []
    cursor_pos = 0

    backspace = 8
    enter = 13

    escape_code = 224
    delete = 83
    left = 75
    right = 77
    home = 71
    end = 79
    ctrl_left = 115
    ctrl_right = 116
    ctrl_home = 119
    ctrl_end = 117

    while user_input != enter:
        char_g = getch()
        user_input = ord(char_g)
        prev_len = len(curr_chars)  # track length for clearing stdout since length of curr_chars might change

        if user_input == backspace:
            if len(curr_chars) > 0 and cursor_pos <= len(curr_chars):
                cursor_pos -= 1
                curr_chars.pop(cursor_pos)

        elif user_input == escape_code:
            user_input = ord(getch())

            if user_input == delete:
                curr_chars.pop(cursor_pos)

            elif user_input == left:
                cursor_pos -= 1

            elif user_input == right:
                if cursor_pos < len(curr_chars):
                    cursor_pos += 1

            elif user_input == home:
                cursor_pos = 0

            elif user_input == end:
                cursor_pos = len(curr_chars)

            elif user_input == ctrl_home:
                curr_chars = curr_chars[cursor_pos:]
                cursor_pos = 0

            elif user_input == ctrl_end:
                curr_chars = curr_chars[:cursor_pos]
                cursor_pos = len(curr_chars)

            elif user_input == ctrl_left:
                try:
                    chars_left_of_cursor = "".join(curr_chars[:cursor_pos])
                    left_closest_space_char_index = [m.span()[0] for m in finditer(" \w", chars_left_of_cursor)][-1]
                    pos_diff = cursor_pos - left_closest_space_char_index - 1
                    cursor_pos -= pos_diff
                except IndexError:
                    cursor_pos = 0

            elif user_input == ctrl_right:
                try:
                    chars_right_of_cursor = "".join(curr_chars[cursor_pos + 1:])
                    right_closest_space_char_index = [m.span()[0] for m in finditer(" \w", chars_right_of_cursor)][0]
                    cursor_pos += right_closest_space_char_index + 2
                except IndexError:
                    cursor_pos = len(curr_chars) - 1

        elif user_input != enter:
            if cursor_pos > len(curr_chars) - 1:
                curr_chars.append(char_g)
            else:
                curr_chars.insert(cursor_pos, char_g)
            cursor_pos += 1

        # clear entire line, write contents of curr_chars, reposition cursor
        stdout.write("\r" + prev_len * " " + "\r")
        stdout.write("".join(curr_chars))
        pos_diff = len(curr_chars) - cursor_pos
        stdout.write("\b" * pos_diff)

    stdout.write("\r" + len(curr_chars) * " " + "\r")
    stdout.write("".join(curr_chars) + "\n")

    return "".join(curr_chars)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM