Python: несоответствия совпадений строк в 2.6 и 3.1 - PullRequest
0 голосов
/ 06 октября 2010

Я написал свой модуль на Python 3.1.2, но теперь мне нужно проверить его на 2.6.4.

Я не собираюсь публиковать весь свой код, так как это может вызвать путаницу.

Краткое объяснение: Я пишу синтаксический анализатор XML (мое первое взаимодействие с XML), который создает объекты из файла XML. Есть много объектов, поэтому у меня есть «модульный тест», который вручную сканирует XML и пытается найти подходящий объект. Он распечатает все, что не соответствует.

Я открываю файл XML и использую простой цикл for для построчного чтения файла. Если я сопоставляю регулярное выражение для «приложения» (XML имеет разные узлы «приложения»), то я добавляю его в свой словарь d в качестве ключа. Я выполняю запрос lxml.etree.xpath () для заголовка и сохраняю его как значение. После того, как я прошёл через все это, я перебираю свой словарь d и пытаюсь сопоставить ключ с моим значением (я должен использовать метод get () из моего класса 'application'). Каждый раз, когда обнаруживается несоответствие, я печатаю ключ и название. Python 3.1.2 содержит все соответствующие элементы в словаре, поэтому ничего не печатается. В 2.6.4 печатается каждое отдельное значение (~ 600). Я не могу понять, почему мои сравнения строк не работают.

Без лишних слов, вот соответствующий код:

    for i in d:                                                                                                        
     if i[1:-2] != d[i].get('id'):                                                                                                                                  
         print('X%sX Y%sY' % (i[1:-3], d[i].get('id')))                                                            

Я нарезаю строки, потому что строки разные. Где ключ будет "9626-2008olympics_Prod-SH" \ n, значение будет 9626-2008olympics_Prod-SH, поэтому я должен сократить кавычки и перевод строки. Я также добавил X и Y в операторы печати, чтобы убедиться в отсутствии каких-либо проблем с пробелами. Вот пример строки вывода:

X9626-2008olympics_Prod-SHX Y9626-2008olympics_Prod-SHY

Не забудьте игнорировать X и Y. Эти строки идентичны. Я не понимаю, почему Python2 не может сравниться с ними.


Edit: Так что проблема, похоже, в том, что я нарезаю. В Python3

if i[1:-2] != d[i].get('id'):

это сравнение отлично работает.

В Python2,

if i[1:-3] != d[i].get('id'):

Я должен изменить смещение на единицу.

Зачем строкам нужны разные смещения? Единственное, о чем я могу думать, это то, что Python2 рассматривает новую строку как два символа (то есть '\' + 'n').

Редактировать 2: Обновлено с запрошенной информацией repr ().

Я добавил небольшой объем кода для получения информации repr () из приведенного выше примера «2008olympics». Я не сделал нарезку. На самом деле это выглядит так, как будто это не проблема юникода. Теперь есть символ "\ r". Python2:

"9626-2008olympics_Prod-SH" \ г \ п ' '9626-2008olympics_Prod-SH'

Python3:

"9626-2008olympics_Prod-SH" \ п " '9626-2008olympics_Prod-SH'

Похоже, этот файл был создан / изменен в Windows. Есть ли в Python2 способ автоматически подавлять '\ r'?

Ответы [ 4 ]

3 голосов
/ 06 октября 2010

Вы print ing i[1:-3], но сравниваете i[1:-2] в цикле.


Очень важный вопрос

Почему вы пишете код для разбора XML, когда lxml сделает все это за вас? Цель модульных тестов - проверить ваш код, а не убедиться, что библиотеки, которые вы используете, работают!

0 голосов
/ 06 октября 2010

Рассел Борогров прав.

В Python 3 по умолчанию используется юникод, и символ новой строки правильно интерпретируется как один символ.Вот почему мое смещение [1: -2] сработало в 3, потому что мне нужно было удалить три символа: "," и \ n.

В Python 2 символ новой строки интерпретируется как два символа, то есть я должен исключить четыре символа и использовать [1: -3].

Я только что добавил проверку Python вручнуюосновная версия.

Вот фиксированный код:

    for i in d:
    # The keys in D contain quotes and a newline which need                                                                                                                                                                              
    # to be removed. In v3, newline = 1 char and in v2,                                                                                                                                                                                  
    # newline = 2 char.                                                                                                                                                                                                                  
    if sys.version_info[0] < 3:
        if i[1:-3] != d[i].get('id'):
            print('%s %s' % (i[1:-3], d[i].get('id')))
    else:
        if i[1:-2] != d[i].get('id'):
             print('%s %s' % (i[1:-2], d[i].get('id')))

Спасибо всем за ответы!Я ценю вашу помощь.

0 голосов
/ 06 октября 2010

repr () и% r формат - ваши друзья ... они показывают вам (для базовых типов, как str / unicode / bytes) именно то, что у вас есть, включая тип.

Вместо

print('X%sX Y%sY' % (i[1:-3], d[i].get('id')))  

сделать

print('%r %r' % (i, d[i].get('id'))) 

Заметьте, что опускается [1:-3], чтобы вы могли видеть, что находится в i, прежде чем нарезать его.

Обновление после комментария"Вы совершенно правы, сравнивая неправильный фрагмент. Однако, как только я изменил его, python2.6 работает, но проблема в python3 сейчас (то есть он не соответствует ни одному объекту ) ":

Как вы открываете файл (два ответа, пожалуйста, для Python 2 и 3). Вы работаете в Windows? Вы пытались получить repr (), как я предложил?

Обновление после фактического ввода, окончательно предоставленного OP:

Если, как оказалось, ваш входной файл был создан в Windows (строки разделены "\r\n"), вы можете читать текстовые файлы Windows и * x переносимо, используя опцию " universal newlines " ... open('datafile.txt', 'rU') на Python2 - читать это . Универсальный режим новой строки по умолчанию в Python3. Обратите внимание, что Python3 документы говорят, что вы можете использовать 'rU' также в Python3; это избавит вас от необходимости проверять, какую версию Python вы используете.

0 голосов
/ 06 октября 2010

Я не понимаю, что вы делаете точно , но вы бы попробовали использовать strip () вместо нарезки и посмотреть, поможет ли это?

for i in d:
    stripped = i.strip()                                                                                                      
    if stripped != d[i].get('id'):                                                                                                                                  
         print('X%sX Y%sY' % (stripped, d[i].get('id')))    
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...