Конфликты 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 и разделите выходы. Если вы видите модуль с тем же именем, но с другим происхождением, вероятно, ваш виновник.