Почему это работает в Python 3 IDLE в Windows, а не в терминале в Ubuntu?

1

У меня есть программа, в которой я использую input() для ввода данных из STDIN.

Я использую ввод для чтения первого слова из строки и использую его как ключ словаря, причем каждое последующее слово добавляется в список, который является значением вышеупомянутого ключа.

Вход находится в файле names.txt:

Victor Bertha Amy Diane Erika Clare
Wyatt Diane Bertha Amy Clare Erika
Xavier Bertha Erika Clare Diane Amy
Yancey Amy Diane Clare Bertha Erika
Zeus Bertha Diane Amy Erika Clare

Amy Zeus Victor Wyatt Yancey Xavier
Bertha Xavier Wyatt Yancey Victor Zeus
Clare Wyatt Xavier Yancey Zeus Victor
Diane Victor Zeus Yancey Xavier Wyatt
Erika Yancey Wyatt Zeus Xavier Victor

Так, например, men["Victor"] = ["Bertha","Amy","Diane","Erika","Clare"].

Код находится в файле GS.py (реализация Gale-Shapley):

if __name__ == "__main__":

    ## Data Dictionary

    ''' Name : Preferences '''
    men = dict()
    women = dict()

    ''' List of unmatched men '''
    freeMen = list()

    ''' Name : How far down in preferences '''
    count = dict()

    ''' Name : Current Match '''
    wife = dict()
    husband = dict()

    ## Reading Input
    data = input("").split("\n")
    print(data)
    readingMen = True
    for l in data:
        line = l.split()
        print(line)
        if len(line) > 1:
            newPerson = line[0]
            newPersonPreferences = list()
            for i in range(1,len(line)):
                newPersonPreferences.append(line[i])
            if readingMen:
                print("man")
                print(newPersonPreferences)
                men[newPerson] = newPersonPreferences
                wife[newPerson] = 0
                count[newPerson] = 0
                freeMen.append(newPerson)
            else:
                print("woman")
                print(newPersonPreferences)
                women[newPerson] = newPersonPreferences
                husband[newPerson] = 0
        elif len(line) == 1:
            raise IOError(l + "\nis an invalid line.")
        else:
            readingMen = False

    ## Proposing
    while len(freeMen) != 0:
        m = freeMen[0]
        w = men[m][count[m]]
        count[m] += 1
        if husband[w] == 0:
            husband[w] = m
            wife[m] = w
            freeMen.remove(m)
        else:
            try:
                if women[w].index(husband[w], women[w].index(m)):
                    freeMen.append(husband[w])
                    wife[husband[w]] = 0
                    husband[w] = m
                    wife[m] = w
                    freeMen.remove(m)
            except ValueError:
                pass

    ## Match Printing
    print()
    for m in wife:
        print(m, wife[m])

При использовании IDLE в Windows я просто вставляю содержимое этого файла и нажимаю enter, и он работает.

Но используя Ubuntu, я делаю python3 GS.py < names.txt и я получаю это:

me@glados:~$ python3 GS.py < names.txt
['Victor Bertha Amy Diane Erika Clare']
['Victor', 'Bertha', 'Amy', 'Diane', 'Erika', 'Clare']
man
['Bertha', 'Amy', 'Diane', 'Erika', 'Clare']
Traceback (most recent call last):
  File "GS.py", line 83, in <module>
    if husband[w] == 0:
KeyError: 'Bertha'

(отредактировано) Теперь, когда я делаю cat names.txt | python3 GS.py cat names.txt | python3 GS.py Я получаю следующее:

ajg9132@glados:~$ cat names.txt | python GS.py
Traceback (most recent call last):
  File "GS.py", line 50, in <module>
    data = input("").split("\n")
  File "<string>", line 1
    Victor Bertha Amy Diane Erika Clare
                ^
SyntaxError: invalid syntax

Я понятия не имею, что делать - вроде невежественного в отношении ввода-вывода. Любая помощь?

Редактирование примечания: Я думал, что две разные команды bash, которые я дал, были эквивалентными, но опять же, я полный noob, поэтому объяснение того, почему они разные, тоже помогло бы...

Чтобы устранить двусмысленность, это для домашней работы Algo... (грустно, что я понимаю алгоритм, но не низкоуровневые детали ОС), и мне нужно иметь конкретную схему ввода и вывода. например

spock $ java GS
Victor Bertha Amy Diane Erika Clare
Wyatt Diane Bertha Amy Clare Erika
Xavier Bertha Erika Clare Diane Amy
Yancey Amy Diane Clare Bertha Erika
Zeus Bertha Diane Amy Erika Clare

Amy Zeus Victor Wyatt Yancey Xavier
Bertha Xavier Wyatt Yancey Victor Zeus
Clare Wyatt Xavier Yancey Zeus Victor
Diane Victor Zeus Yancey Xavier Wyatt
Erika Yancey Wyatt Zeus Xavier Victor

Victor Amy
Wyatt Clare
Xavier Bertha
Yancy Erika
Zeus Diane
spock $

Единственная причина, по которой я этого не делал, заключалась в том, что вставка нескольких строк текста в PuTTY заставила bash попытаться интерпретировать каждую строку как команду. Я даже не могу.

  • 1
    Вы пытались добавить отладочную печать и посмотреть, где и почему это происходит? Я думаю, никто не хочет возиться со всем вашим кодом.
  • 0
    У меня плохая привычка удалять все мои отладочные операторы, как только мой код работает на одной платформе, прежде чем я проверю его на другой. Конечно! BRB.
Показать ещё 8 комментариев
Теги:
io
python-idle

1 ответ

3
Лучший ответ

Значение input() изменилось.

В Python 3.2: http://docs.python.org/py3k/library/functions.html#input

В Python 2.7.2: http://docs.python.org/library/functions.html#input

Вы можете увидеть это намного проще с помощью двух небольших тестовых программ. Единственное отличие заключается в том, что один использует интерпретатор Python 2.7, а другой использует интерпретатор Python 3.2:

$ cat input27.py 
#!/usr/bin/python2.7
data = input("")

for l in data.split("\n"):
    print(l)
$ cat input32.py 
#!/usr/bin/python3.2
data = input("")

for l in data.split("\n"):
    print(l)
$ ./input27.py < names.txt 
Traceback (most recent call last):
  File "./input27.py", line 2, in <module>
    data = input("")
  File "<string>", line 1
    Victor Bertha Amy Diane Erika Clare
                ^
SyntaxError: invalid syntax
$ ./input32.py < names.txt 
Victor Bertha Amy Diane Erika Clare
$ 

Обратите внимание, что хотя версия Python 3.2 не выдает ошибок, она также не печатает все строки в names.txt как можно было бы ожидать.

Я не думаю, что метод input() стоит использовать. Легче будет использовать новую for line in file: вместо этого:

$ cat fixed_input27.py 
#!/usr/bin/python2.7

import sys

for line in sys.stdin:
    print(line.split()[0])
$ cat fixed_input32.py 
#!/usr/bin/python3.2

import sys

for line in sys.stdin:
    print(line.split()[0])
$ ./fixed_input27.py < names.txt 
Victor
Wyatt
Xavier
Yancey
Zeus
Amy
Bertha
Clare
Diane
Erika
$ ./fixed_input32.py < names.txt 
Victor
Wyatt
Xavier
Yancey
Zeus
Amy
Bertha
Clare
Diane
Erika
$ 

(Я удалил одну пустую строку из names.txt потому что это заставило эту простую программу выбросить ошибку. Это не будет проблемой в вашей полноценной программе, потому что вы правильно обрабатываете пустую строку.)

Я не могу объяснить, почему input() работал под Windows, но input() чувствует себя довольно ужасным интерфейсом (кто думал, что запуск пользовательского ввода через eval был хорошей идеей?!? Sheesh), чтобы просто переписать его,

Обновить

Хорошо, я был достаточно заинтригован, чтобы решить эту проблему до конца. Я взял весь ваш код отладки и переключился на использование for l in sys.stdin: approach:

$ ./GS.py 
Victor Bertha Amy Diane Erika Clare
Wyatt Diane Bertha Amy Clare Erika
Xavier Bertha Erika Clare Diane Amy
Yancey Amy Diane Clare Bertha Erika
Zeus Bertha Diane Amy Erika Clare

Amy Zeus Victor Wyatt Yancey Xavier
Bertha Xavier Wyatt Yancey Victor Zeus
Clare Wyatt Xavier Yancey Zeus Victor
Diane Victor Zeus Yancey Xavier Wyatt
Erika Yancey Wyatt Zeus Xavier Victor

Wyatt Clare
Xavier Bertha
Yancey Erika
Zeus Diane
Victor Amy
$ cat GS.py 
#!/usr/bin/python3.2

if __name__ == "__main__":
    import sys

    ## Data Dictionary

    ''' Name : Preferences '''
    men = dict()
    women = dict()

    ''' List of unmatched men '''
    freeMen = list()

    ''' Name : How far down in preferences '''
    count = dict()

    ''' Name : Current Match '''
    wife = dict()
    husband = dict()

    ## Reading Input
    readingMen = True
    for l in sys.stdin:
        line = l.split()
        if len(line) > 1:
            newPerson = line[0]
            newPersonPreferences = list()
            for i in range(1,len(line)):
                newPersonPreferences.append(line[i])
            if readingMen:
                men[newPerson] = newPersonPreferences
                wife[newPerson] = 0
                count[newPerson] = 0
                freeMen.append(newPerson)
            else:
                women[newPerson] = newPersonPreferences
                husband[newPerson] = 0
        elif len(line) == 1:
            raise IOError(l + "\nis an invalid line.")
        else:
            readingMen = False

    ## Proposing
    while len(freeMen) != 0:
        m = freeMen[0]
        w = men[m][count[m]]
        count[m] += 1
        if husband[w] == 0:
            husband[w] = m
            wife[m] = w
            freeMen.remove(m)
        else:
            try:
                if women[w].index(husband[w], women[w].index(m)):
                    freeMen.append(husband[w])
                    wife[husband[w]] = 0
                    husband[w] = m
                    wife[m] = w
                    freeMen.remove(m)
            except ValueError:
                pass

    ## Match Printing
    print()
    for m in wife:
        print(m, wife[m])

$ 

Обратите внимание, что вам нужно нажать ^D когда вы закончите вставку, если вы запустите его таким образом. (Я предпочитаю перенаправление IO ./GS.py < names.txt, но если ваш профессор будет копировать и вставлять, то убедитесь, что ваш профессор знает, чтобы нажать ^D чтобы сигнализировать о конце ввода.)

  • 0
    Хотя я согласен с вашей жалобой на Windows, я думаю, что input () работал в Windows, потому что я вставил текст в приглашение в сеансе IDLE, который отличается от передачи (это слово?) Содержимого файла в входной поток. Тем не менее, я не могу использовать ваше решение ... Я отредактирую свой вопрос с примером ввода и вывода для этого задания.
  • 0
    Посмотрел твои правки ... это действительно работает! ... на Ubuntu. В Windows я получаю следующее: Traceback (последний вызов был последним): файл "D: \ yada yada \ GS.py", строка 52, в <module> для l в sys.stdin: TypeError: объект RPCProxy не повторяется `
Показать ещё 9 комментариев

Ещё вопросы

Сообщество Overcoder
Наверх
Меню