복붙노트

[PYTHON] 새 줄을 삽입하지 않고도 사용자 입력을받을 수 있습니까?

PYTHON

새 줄을 삽입하지 않고도 사용자 입력을받을 수 있습니까?

쉼표를 추가하여 인쇄를 중단 할 수 있음을 알고 있습니다.

print "Hello, world!",

하지만 raw_input이 개행을 작성하는 것을 중단시키는 방법은 무엇입니까?

print "Hello, ",
name = raw_input()
print ", how do you do?"

결과:

결과 :

해결법

  1. ==============================

    1.간단히 말해서 : 당신은 할 수 없습니다.

    간단히 말해서 : 당신은 할 수 없습니다.

    raw_input ()은 후행 줄 바꿈을 포함하여 사용자가 입력 한 텍스트를 항상 에코합니다. 즉, 사용자가 입력하는 내용이 표준 출력에 인쇄됩니다.

    이를 방지하려면 curses 모듈과 같은 터미널 제어 라이브러리를 사용해야합니다. 이것은 휴대용이 아닙니다. 예를 들어 Windows 시스템에서는 curses를 사용할 수 없습니다.

  2. ==============================

    2.이것은 다소 우회하지만 변수 이름에는 아무 것도 지정하지 않습니다.

    이것은 다소 우회하지만 변수 이름에는 아무 것도 지정하지 않습니다.

    print("Hello, {0}, how do you do?".format(raw_input("Enter name here: ")))
    

    전체 메시지를 인쇄하기 전에 사용자에게 이름을 묻습니다.

  3. ==============================

    3.나는 아무도 작동하는 해결책을 제시하지 못했기 때문에 나는 그것을 줄 것이라고 결정했다. Ferdinand Beyer가 말했듯이, raw_input ()이 사용자가 입력 한 후에 새로운 라인을 출력하지 못하게하는 것은 불가능합니다. 그러나 이전 회선으로 돌아갈 수 있습니다. 나는 그것을 하나의 라이너로 만들었습니다. 다음을 사용할 수 있습니다 :

    나는 아무도 작동하는 해결책을 제시하지 못했기 때문에 나는 그것을 줄 것이라고 결정했다. Ferdinand Beyer가 말했듯이, raw_input ()이 사용자가 입력 한 후에 새로운 라인을 출력하지 못하게하는 것은 불가능합니다. 그러나 이전 회선으로 돌아갈 수 있습니다. 나는 그것을 하나의 라이너로 만들었습니다. 다음을 사용할 수 있습니다 :

    print '\033[{}C\033[1A'.format(len(x) + y),
    

    여기서 x는 주어진 사용자 입력 길이의 정수이고, y는 raw_input ()의 문자열 길이입니다. 모든 터미널에서 작동하지 않을 수도 있지만 (이 방법에 대해 배웠을 때 읽었던 것처럼), 제 문제는 제대로 작동합니다. 나는 쿠분투 14.04를 사용하고있다. 문자열 '\ 033 [4C'는 오른쪽에 4 개의 인덱스를 점프하는 데 사용되므로 ''* 4와 같습니다. 같은 식으로 '\ 033 [1A'는 1 행 위로 이동하는 데 사용됩니다. 문자열의 마지막 색인에서 문자 A, B, C 또는 D를 사용하여 위, 아래, 오른쪽 및 왼쪽으로 각각 이동할 수 있습니다. 한 줄 위로 이동하면 그 자리에있는 기존의 인쇄 된 문자가 있으면 삭제됩니다.

  4. ==============================

    4.새 행을 만들지 않으려면 raw_input 대신 getpass를 사용할 수 있습니다!

    새 행을 만들지 않으려면 raw_input 대신 getpass를 사용할 수 있습니다!

    import sys, getpass
    
    def raw_input2(value="",end=""):
        sys.stdout.write(value)
        data = getpass.getpass("")
        sys.stdout.write(data)
        sys.stdout.write(end)
        return data
    
  5. ==============================

    5.Nick K가 말했듯이, 개행 문자가 반향되기 전에 텍스트 커서를 다시 움직여야합니다. 문제는 오른쪽으로 이동하기 위해 이전 줄의 길이를 쉽게 얻을 수 없다는 것입니다. 인쇄 된 모든 문자열을 저장하고 프롬프트에 입력 한 다음 자체 변수에 입력하지 않도록해야합니다.

    Nick K가 말했듯이, 개행 문자가 반향되기 전에 텍스트 커서를 다시 움직여야합니다. 문제는 오른쪽으로 이동하기 위해 이전 줄의 길이를 쉽게 얻을 수 없다는 것입니다. 인쇄 된 모든 문자열을 저장하고 프롬프트에 입력 한 다음 자체 변수에 입력하지 않도록해야합니다.

    다음은 터미널에서 마지막 줄을 자동으로 저장하여 (이 방법을 사용한다면)이를 수정하는 클래스입니다 (Python 3). 이것의 장점은 터미널 컨트롤 라이브러리를 사용하는 것과 비교하여 최신 버전의 Windows와 * NIX 운영 체제 모두에서 표준 터미널에서 작동한다는 것입니다. 또한 입력을 시작하기 전에 'Hello'프롬프트가 출력됩니다.

    Windows에서 v1511의 Windows 10이 아닌 경우 colorama 모듈을 설치해야합니다. 그렇지 않으면 ANSI 커서 이동 지원이 해당 버전에서 제공되므로이 기능이 작동하지 않습니다.

    # For the sys.stdout file-like object
    import sys
    import platform
    
    if platform.system() == 'Windows':
        try:
            import colorama
        except ImportError:
            import ctypes
            kernel32 = ctypes.windll.kernel32
            # Enable ANSI support on Windows 10 v1511
            kernel32.SetConsoleMode(kernel32.GetStdHandle(-11), 7)
        else:
            colorama.init()
    else:
        # Fix Linux arrow key support in Python scripts
        import readline
    
    
    class TempHistory:
        """Record one line from the terminal.
    
        It is necessary to keep track of the last line on the terminal so we
        can move the text cursor rightward and upward back into the position
        before the newline from the `input` function was echoed.
    
        Note: I use the term 'echo' to refer to when text is
        shown on the terminal but might not be written to `sys.stdout`.
    
        """
    
        def __init__(self):
            """Initialise `line` and save the `print` and `input` functions.
    
            `line` is initially set to '\n' so that the `record` method
            doesn't raise an error about the string index being out of range.
    
            """
            self.line = '\n'
            self.builtin_print = print
            self.builtin_input = input
    
        def _record(self, text):
            """Append to `line` or overwrite it if it has ended."""
            if text == '':
                # You can't record nothing
                return
            # Take into account `text` being multiple lines
            lines = text.split('\n')
            if text[-1] == '\n':
                last_line = lines[-2] + '\n'
                # If `text` ended with a newline, then `text.split('\n')[-1]`
                # would have merely returned the newline, and not the text
                # preceding it
            else:
                last_line = lines[-1]
            # Take into account return characters which overwrite the line
            last_line = last_line.split('\r')[-1]
            # `line` is considered ended if it ends with a newline character
            if self.line[-1] == '\n':
                self.line = last_line
            else:
                self.line += last_line
    
        def _undo_newline(self):
            """Move text cursor back to its position before echoing newline.
    
            ANSI escape sequence: `\x1b[{count}{command}`
            `\x1b` is the escape code, and commands `A`, `B`, `C` and `D` are
            for moving the text cursor up, down, forward and backward {count}
            times respectively.
    
            Thus, after having echoed a newline, the final statement tells
            the terminal to move the text cursor forward to be inline with
            the end of the previous line, and then move up into said line
            (making it the current line again).
    
            """
            line_length = len(self.line)
            # Take into account (multiple) backspaces which would
            # otherwise artificially increase `line_length`
            for i, char in enumerate(self.line[1:]):
                if char == '\b' and self.line[i-1] != '\b':
                    line_length -= 2
            self.print('\x1b[{}C\x1b[1A'.format(line_length),
                       end='', flush=True, record=False)
    
        def print(self, *args, sep=' ', end='\n', file=sys.stdout, flush=False,
                  record=True):
            """Print to `file` and record the printed text.
    
            Other than recording the printed text, it behaves exactly like
            the built-in `print` function.
    
            """
            self.builtin_print(*args, sep=sep, end=end, file=file, flush=flush)
            if record:
                text = sep.join([str(arg) for arg in args]) + end
                self._record(text)
    
        def input(self, prompt='', newline=True, record=True):
            """Return one line of user input and record the echoed text.
    
            Other than storing the echoed text and optionally stripping the
            echoed newline, it behaves exactly like the built-in `input`
            function.
    
            """
            if prompt == '':
                # Prevent arrow key overwriting previously printed text by
                # ensuring the built-in `input` function's `prompt` argument
                # isn't empty
                prompt = ' \b'
            response = self.builtin_input(prompt)
            if record:
                self._record(prompt)
                self._record(response)
            if not newline:
                self._undo_newline()
            return response
    
    
    record = TempHistory()
    # For convenience
    print = record.print
    input = record.input
    
    print('Hello, ', end='', flush=True)
    name = input(newline=False)
    print(', how do you do?)
    
  6. ==============================

    6.개행을 백 트랙킹하는 대신 내장 된 입력 함수를 에뮬레이트하는 모든 함수를 정의하고 Enter (응답을 반환 함)를 제외한 모든 응답을 응답 변수에 추가하고 Backspace, Del, Home, End, 화살표 키, 라인 히스토리, KeyboardInterrupt, EOFError, SIGTSTP 및 클립 보드에서 붙여 넣기. 매우 간단합니다.

    개행을 백 트랙킹하는 대신 내장 된 입력 함수를 에뮬레이트하는 모든 함수를 정의하고 Enter (응답을 반환 함)를 제외한 모든 응답을 응답 변수에 추가하고 Backspace, Del, Home, End, 화살표 키, 라인 히스토리, KeyboardInterrupt, EOFError, SIGTSTP 및 클립 보드에서 붙여 넣기. 매우 간단합니다.

    Windows에서 일반적인 입력 기능과 같이 화살표 키를 사용하여 회선 기록을 사용하려면 pyreadline을 설치해야합니다. 기능이 여전히 올바르지 않으므로 불완전합니다. 또한 v1511 이상의 Windows 10을 사용하고 있지 않다면 colorama 모듈을 설치해야합니다 (Linux 또는 macOS를 사용하는 경우에는 아무 것도 할 필요가 없습니다).

    또한 '\ xe0'을 사용하여 특수 문자를 나타내는 msvcrt.getwch로 인해 'à'을 (를) 입력 할 수 없습니다. 그래도 붙여 넣을 수 있어야합니다.

    아래는 업데이트 된 Windows 10 시스템 (적어도 v1511 이상), Debian 기반 Linux 배포판 및 macOS 및 기타 * NIX 운영 체제에서이 작업을 수행하는 코드입니다. 또한 Windows에 pyreadline을 설치했는지 여부에 관계없이 작동해야하지만 일부 기능이 부족합니다.

    windows_specific.py에서 :

    """Windows-specific functions and variables for input_no_newline."""
    import ctypes
    from msvcrt import getwch  # pylint: disable=import-error, unused-import
    from shared_stuff import ANSI
    
    try:
        import colorama  # pylint: disable=import-error
    except ImportError:
        kernel32 = ctypes.windll.kernel32
        # Enable ANSI support to move the text cursor
        kernel32.SetConsoleMode(kernel32.GetStdHandle(-11), 7)
    else:
        colorama.init()
    
    
    def get_clipboard_data():
        """Return string previously copied from Windows clipboard.
    
        Adapted from <http://stackoverflow.com/a/23285159/6379747>.
    
        """
        CF_TEXT = 1
        user32 = ctypes.windll.user32
        user32.OpenClipboard(0)
        try:
            if user32.IsClipboardFormatAvailable(CF_TEXT):
                data = user32.GetClipboardData(CF_TEXT)
                data_locked = kernel32.GlobalLock(data)
                text = ctypes.c_char_p(data_locked)
                kernel32.GlobalUnlock(data_locked)
        finally:
            user32.CloseClipboard()
        return text.value
    
    
    def sigtstp():
        """Raise EOFError from Ctrl-Z since SIGTSTP doesn't exist on Windows."""
        raise EOFError
    
    
    input_code = {
        **ANSI,
        'CSI': [['\xe0', '\x00'], ''],
        'up': 'H',
        'down': 'P',
        'right': 'M',
        'left': 'K',
        'end': 'O',
        'home': 'G',
        'backspace': '\b',
        'del': 'S',
    }
    

    unix_specific.py에서 :

    """Functions and variables for Debian-based Linux distros and macOS."""
    import sys
    import os
    import tty
    import signal
    import termios
    from shared_stuff import ANSI
    
    def getwch():
        """Return a single character from user input without echoing.
    
        ActiveState code, adapted from
        <http://code.activestate.com/recipes/134892> by Danny Yoo under
        the Python Software Foundation license.
    
        """
        file_descriptor = sys.stdin.fileno()
        old_settings = termios.tcgetattr(file_descriptor)
        try:
            tty.setraw(file_descriptor)
            char = sys.stdin.read(1)
        finally:
            termios.tcsetattr(file_descriptor, termios.TCSADRAIN, old_settings)
        return char
    
    
    def get_clipboard_data():
        """Return nothing; *NIX systems automagically change sys.stdin."""
        return ''
    
    
    def sigtstp():
        """Suspend the script."""
        os.kill(os.getpid(), signal.SIGTSTP)
    
    
    input_code = {
        **ANSI,
        'CSI': ['\x1b', '['],
        'backspace': '\x7f',
        'del': ['3', '~'],
    }
    

    readline_available.py :

    """Provide functions for up and down arrows if readline is installed.
    
    Basically to prevent duplicate code and make it work on systems without
    readline.
    
    """
    try:
        import readline
    except ImportError:
        import pyreadline as readline
    from shared_stuff import move_cursor
    
    
    def init_history_index():
        """Return index for last element of readline.get_history_item."""
        # readline.get_history_item is one-based
        return readline.get_current_history_length() + 1
    
    
    def restore_history(history_index, replaced, cursor_position):
        """Replace 'replaced' with history and return the replacement."""
        try:
            replacement = readline.get_history_item(history_index)
        except IndexError:
            replacement = None
        if replacement is not None:
            move_cursor('right', len(replaced) - cursor_position)
            print('\b \b' * len(replaced), end='', flush=True)
            print(replacement, end='', flush=True)
            return replacement
        return replaced
    
    
    def store_and_replace_history(history_index, replacement, old_history):
        """Store history and then replace it."""
        old_history[history_index] = readline.get_history_item(history_index)
        try:
            readline.replace_history_item(history_index - 1, replacement)
        except AttributeError:
        # pyreadline is incomplete
            pass
    
    
    def handle_prev_history(history_index, replaced, old_history,
                            input_replaced, history_modified):
        """Handle some up-arrow logic."""
        try:
            history = readline.get_history_item(history_index - 1)
        except IndexError:
            history = None
        if history is not None:
            if history_index > readline.get_current_history_length():
                readline.add_history(replaced)
                input_replaced = True
            else:
                store_and_replace_history(
                    history_index, replaced, old_history)
                history_modified = True
            history_index -= 1
        return (history_index, input_replaced, history_modified)
    
    
    def handle_next_history(history_index, replaced, old_history,
                            input_replaced, history_modified):
        """Handle some down-arrow logic."""
        try:
            history = readline.get_history_item(history_index + 1)
        except IndexError:
            history = None
        if history is not None:
            store_and_replace_history(history_index, replaced, old_history)
            history_modified = True
            history_index += 1
            input_replaced = (not history_index
                                == readline.get_current_history_length())
        return (history_index, input_replaced, history_modified)
    
    
    def finalise_history(history_index, response, old_history,
                         input_replaced, history_modified):
        """Change history before the response will be returned elsewhere."""
        try:
            if input_replaced:
                readline.remove_history_item(history_index - 1)
            elif history_modified:
                readline.remove_history_item(history_index - 1)
                readline.add_history(old_history[history_index - 1])
        except AttributeError:
        # pyreadline is also missing remove_history_item
            pass
        readline.add_history(response)
    

    readline_unavailable.py :

    """Provide dummy functions for if readline isn't available."""
    # pylint: disable-msg=unused-argument
    
    
    def init_history_index():
        """Return an index of 1 which probably won't ever change."""
        return 1
    
    
    def restore_history(history_index, replaced, cursor_position):
        """Return the replaced thing without replacing it."""
        return replaced
    
    
    def store_and_replace_history(history_index, replacement, old_history):
        """Don't store history."""
        pass
    
    
    def handle_prev_history(history_index, replaced, old_history,
                            input_replaced, history_modified):
        """Return 'input_replaced' and 'history_modified' without change."""
        return (history_index, input_replaced, history_modified)
    
    
    def handle_next_history(history_index, replaced, old_history,
                            input_replaced, history_modified):
        """Also return 'input_replaced' and 'history_modified'."""
        return (history_index, input_replaced, history_modified)
    
    
    def finalise_history(history_index, response, old_history,
                         input_replaced, history_modified):
        """Don't change nonexistent history."""
        pass
    

    shared_stuff.py에서 :

    """Provide platform-independent functions and variables."""
    ANSI = {
        'CSI': '\x1b[',
        'up': 'A',
        'down': 'B',
        'right': 'C',
        'left': 'D',
        'end': 'F',
        'home': 'H',
        'enter': '\r',
        '^C': '\x03',
        '^D': '\x04',
        '^V': '\x16',
        '^Z': '\x1a',
    }
    
    
    def move_cursor(direction, count=1):
        """Move the text cursor 'count' times in the specified direction."""
        if direction not in ['up', 'down', 'right', 'left']:
            raise ValueError("direction should be either 'up', 'down', 'right' "
                             "or 'left'")
        # A 'count' of zero still moves the cursor, so this needs to be
        # tested for.
        if count != 0:
            print(ANSI['CSI'] + str(count) + ANSI[direction], end='', flush=True)
    
    
    def line_insert(text, extra=''):
        """Insert text between terminal line and reposition cursor."""
        if not extra:
        # It's not guaranteed that the new line will completely overshadow
        # the old one if there is no extra. Maybe something was 'deleted'?
            move_cursor('right', len(text) + 1)
            print('\b \b' * (len(text)+1), end='', flush=True)
        print(extra + text, end='', flush=True)
        move_cursor('left', len(text))
    

    마지막으로, input_no_newline.py에서 :

    #!/usr/bin/python3
    """Provide an input function that doesn't echo a newline."""
    try:
    from windows_specific import getwch, get_clipboard_data, sigtstp, input_code
    except ImportError:
        from unix_specific import getwch, get_clipboard_data, sigtstp, input_code
    try:
        from readline_available import (init_history_index, restore_history,
                                        store_and_replace_history,
                                        handle_prev_history, handle_next_history,
                                        finalise_history)
    except ImportError:
        from readline_unavailable import (init_history_index, restore_history,
                                          store_and_replace_history,
                                          handle_prev_history, handle_next_history,
                                          finalise_history)
    from shared_stuff import ANSI, move_cursor, line_insert
    
    
    def input_no_newline(prompt=''):  # pylint: disable=too-many-branches, too-many-statements
        """Echo and return user input, except for the newline."""
        print(prompt, end='', flush=True)
        response = ''
        position = 0
        history_index = init_history_index()
        input_replaced = False
        history_modified = False
        replacements = {}
    
        while True:
            char = getwch()
            if char in input_code['CSI'][0]:
                char = getwch()
                # Relevant input codes are made of two to four characters
                if char == input_code['CSI'][1]:
                    # *NIX uses at least three characters, only the third is
                    # important
                    char = getwch()
                if char == input_code['up']:
                    (history_index, input_replaced, history_modified) = (
                        handle_prev_history(
                            history_index, response, replacements, input_replaced,
                            history_modified))
                    response = restore_history(history_index, response, position)
                    position = len(response)
                elif char == input_code['down']:
                    (history_index, input_replaced, history_modified) = (
                        handle_next_history(
                            history_index, response, replacements, input_replaced,
                            history_modified))
                    response = restore_history(history_index, response, position)
                    position = len(response)
                elif char == input_code['right'] and position < len(response):
                    move_cursor('right')
                    position += 1
                elif char == input_code['left'] and position > 0:
                    move_cursor('left')
                    position -= 1
                elif char == input_code['end']:
                    move_cursor('right', len(response) - position)
                    position = len(response)
                elif char == input_code['home']:
                    move_cursor('left', position)
                    position = 0
                elif char == input_code['del'][0]:
                    if ''.join(input_code['del']) == '3~':
                        # *NIX uses '\x1b[3~' as its del key code, but only
                        # '\x1b[3' has currently been read from sys.stdin
                        getwch()
                    backlog = response[position+1 :]
                    response = response[:position] + backlog
                    line_insert(backlog)
            elif char == input_code['backspace']:
                if position > 0:
                    backlog = response[position:]
                    response = response[: position-1] + backlog
                    print('\b', end='', flush=True)
                    position -= 1
                    line_insert(backlog)
            elif char == input_code['^C']:
                raise KeyboardInterrupt
            elif char == input_code['^D']:
                raise EOFError
            elif char == input_code['^V']:
                paste = get_clipboard_data()
                backlog = response[position:]
                response = response[:position] + paste + backlog
                position += len(paste)
                line_insert(backlog, extra=paste)
            elif char == input_code['^Z']:
                sigtstp()
            elif char == input_code['enter']:
                finalise_history(history_index, response, replacements,
                                 input_replaced, history_modified)
                move_cursor('right', len(response) - position)
                return response
            else:
                backlog = response[position:]
                response = response[:position] + char + backlog
                position += 1
                line_insert(backlog, extra=char)
    
    
    def main():
        """Called if script isn't imported."""
        # "print(text, end='')" is equivalent to "print text,", and 'flush'
        # forces the text to appear, even if the line isn't terminated with
        # a '\n'
        print('Hello, ', end='', flush=True)
        name = input_no_newline()  # pylint: disable=unused-variable
        print(', how do you do?')
    
    
    if __name__ == '__main__':
        main()
    

    보시다시피, 다른 운영 체제를 다루어야하고 기본적으로 C가 아닌 파이썬에서 기본 제공 함수를 다시 구현해야하기 때문에 그다지 많은 작업이 필요하지 않습니다. 더 간단한 TempHistory 클래스를 사용하는 것이 좋습니다. 나는 복잡한 응답을 내장 함수에 그대로 두는 또 다른 대답을 만들었다.

  7. ==============================

    7.나는 이것을 단순히 사용할 수 있다고 생각한다.

    나는 이것을 단순히 사용할 수 있다고 생각한다.

     name=input("Hello , ")
    
  8. from https://stackoverflow.com/questions/7173850/possible-to-get-user-input-without-inserting-a-new-line by cc-by-sa and MIT license