Конфликты python в двух внешних пакетах

Я пишу код для объединения функций из библиотеки RSS-ридера python rawdog и библиотеки веб-скинов BeautifulSoup. Существует конфликт где-то во внутренностях, которые я пытаюсь преодолеть.

Я могу реплицировать проблему с помощью этого упрощенного кода:

    import sys, gzip
    def scrape(filename):
        contents = gzip.open(filename,'rb').read()
        contents = contents.decode('utf-8','replace')
        import BeautifulSoup as BS
        print 'before rawdog: ', len(BS.BeautifulSoup(contents)) # prints 4, correct answer
        from rawdoglib import rawdog as rd
        print 'after rawdog: ', len(BS.BeautifulSoup(contents)) # prints 3, incorrect answer

Неважно, в каком порядке или где я делаю импорт, импорт rawdog всегда приводит к тому, что метод BS.BeautifulSoup() возвращает неверный ответ. На самом деле мне не нужен rawdog, когда я получаю необходимость в BeautifulSoup, поэтому я попытался удалить пакет в этот момент, но BS все еще сломан. Исправления, которые я пробовал, которые не работали:

  • Я заметил, что код rawdog делает собственный импорт BeautifulSoup. Поэтому я попытался удалить import BeautifulSoup из кода rawdog и повторно установить rawdog
  • удаление модулей rawdog перед импортом BeautifulSoup:
    • for x in filter(lambda y: y.startswith('rawdog'), sys.modules.keys()): del sys.modules[x]
  • импорт более конкретных классов/методов из rawdog, например from rawdoglib.rawdog import FeedState
  • дать методу проблемы новое имя до и после импорта rawdog: from BeautifulSoup import BeautifulSoup as BS
  • from __future__ import absolute_import

Не повезло, я всегда получаю len (BeautifulSoup (содержимое)) == 3, если rawdog был когда-либо импортирован в пространство имен. Оба пакета достаточно сложны, что я не смог точно определить, что проблема перекрывает, и я не уверен, какие инструменты использовать, чтобы попытаться понять это, кроме поиска через dir (BeautifulSoup) и dir ( rawdog), где я не нашел хороших подсказок.

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

Дальнейшая отладка! Я идентифицировал этот блок во входном тексте как проблемный:

    function SwitchMenu(obj){
      if(document.getElementById){
      var el = document.getElementById(obj);
      var ar = document.getElementById("masterdiv").getElementsByTagName("span"); //DynamicDrive.com change
         if(el.style.display != "block"){ //DynamicDrive.com change
         for (var i=0; i<ar.length; i++){
            if (ar[i].className=="submenu") //DynamicDrive.com change
            ar[i].style.display = "none";
      }
      el.style.display = "block";
      }else{
        el.style.display = "none";
    }
}

}

Если я прокомментирую этот блок, я получаю правильный синтаксический анализ через BeautifulSoup с импортом rawdog или без него. С блоком rawdog + BeautifulSoup неисправен. Так что я должен просто искать свой вход для такого блока, или есть лучший способ обхода?

Ответ 1

Это ошибка в rawdoglib.feedparser.py. rawdog - патч обезьяны smglib: в строке 198 он гласит:

if sgmllib.endbracket.search(' <').start(0):
    class EndBracketMatch:
        endbracket = re.compile('''([^'"<>]|"[^"]*"(?=>|/|\s|\w+=)|'[^']*'(?=>|/|\s|\w+=))*(?=[<>])|.*?(?=[<>])''')
        def search(self,string,index=0):
            self.match = self.endbracket.match(string,index)
            if self.match: return self
        def start(self,n):
            return self.match.end(n)
    sgmllib.endbracket = EndBracketMatch()

Это script, чтобы воспроизвести ошибку:

contents = '''<a><ar "none";                                                 
</a> '''                                                                     
import BeautifulSoup as BS                                                   
print 'before rawdog: ', len(BS.BeautifulSoup(contents)) # prints 4, correct answer
from rawdoglib import rawdog as rd                                           
print 'after rawdog: ', len(BS.BeautifulSoup(contents)) # prints 3, incorrect

Он разбивается на "<" внутри тега "a". В фрагменте OP он запускается по строке: for (var i=0; i<ar.length; i++){ (обратите внимание на "<" char).

Проблема, отправленная на rawdog ML: http://lists.us-lot.org/pipermail/rawdog-users/2012-August/000327.html

Ответ 2

Я думаю, что проблема, с которой вы сталкиваетесь, представляет собой цепочку imports; что два разных места, в которые вы импортируете пакет BS, конфликтуют.

Этот поток может быть тем, что вам нужно.

(Кроме того, пакет BS - замечательная вещь, чтобы иметь возможность говорить в серьезном контексте.)

Ответ 3

Если rawdog может вызвать ошибку без импорта BeautifulSoup (я полагаю, вы проверили, что он не импортирован косвенно?), они должны иметь общую зависимость, которая каким-то образом загружается непоследовательно. Но проблема не должна быть обезболивающей: если они загружают разные версии одной и той же библиотеки, вы можете получить непоследовательное поведение. Например, если один из них использует специальный путь импорта, предоставляет собственную версию модуля верхнего уровня или имеет такой код:

try: 
    import ElementPath 
except ImportError: 
    ElementPath = _SimpleElementPath()

Чтобы узнать, не является ли эта проблема, попробуйте выполнить следующее: Загрузите BeautifulSoup самостоятельно, ничего более, и выгрузите список модулей и их местоположение:

import BeautifulSoup
import sys
sys.stdout = open("soup-modules.txt", "w")
for k,v in sorted(sys.modules.items()):
    if v:
        print k, v.__dict__.get('__file__')

Затем сделайте то же самое с rawdog и разделите выходы. Если вы видите модуль с тем же именем, но с другим происхождением, вероятно, ваш виновник.