两个外部包中的python冲突

时间:2012-08-13 15:06:17

标签: python packages conflict

我正在编写代码来组合python rawdog RSS阅读器库和BeautifulSoup webscraping库中的函数。在我想要克服的内脏中存在冲突。

我可以用这个简化的代码复制问题:

    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()方法返回错误的响应。当我需要BeautifulSoup时,我实际上不再需要rawdog,所以我在那时尝试删除了包,但是BS仍然坏了。我尝试过的修复程序没有用到:

  • 我注意到rawdog代码自己导入了BeautifulSoup。所以我尝试从rawdog代码中删除import BeautifulSoup并重新安装rawdog
  • 在导入BeautifulSoup之前删除rawdog模块:
    • 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

没有运气,如果将rawdog导入命名空间,我总是得到len(BeautifulSoup(内容))== 3。这两个软件包都很复杂,以至于我无法确切地知道问题重叠是什么,而且我不知道用什么工具来解决这个问题,除了搜索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";
    }
}

}

如果我注释掉这个块,那么无论是否使用rawdog导入,我都可以通过BeautifulSoup获得正确的解析。使用块,rawdog + BeautifulSoup是错误的。那么我应该只搜索我的输入这样的块,还是有更好的解决方法?

3 个答案:

答案 0 :(得分:4)

这是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()

这是一个重现错误的脚本:

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

打破了“&lt;”在“a”标签内。在OP的片段中,它由以下行触发:for (var i=0; i<ar.length; i++){(注意“&lt;”char)。

在rawdog的ML上提交的问题:http://lists.us-lot.org/pipermail/rawdog-users/2012-August/000327.html

答案 1 :(得分:0)

我认为你遇到的问题是imports的链条;您导入BS包的两个不同地方存在冲突。

This thread可能就是您所需要的。

(另外,BS包可以在严肃的背景下说出来。)

答案 2 :(得分:0)

如果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执行相同操作并对输出进行差异处理。如果您看到一个名称相同但来源不同的模块,那可能就是您的罪魁祸首。