1

我在使用 spynner 时遇到了一个奇怪的错误,尽管这个问题是一个通用问题。Spynner 是用于 python 的有状态的网络浏览器模块。它在工作时工作正常,但我几乎每次运行都失败了——

Traceback (most recent call last):
  File "/usr/local/lib/python2.7/dist-packages/spynner-2.16.dev0-py2.7.egg/spynner/browser.py", line 1651, in createRequest
    self.cookies,
AttributeError: 'Browser' object has no attribute 'cookies'
Segmentation fault (core dumped)

这里的问题是它的段错误而不是让我继续。

查看 spynner 的代码,我发现 cookies 变量实际上是在__init__()Browser 类的函数中初始化的,如下所示:

self.cookies = []

现在在失败时,它真的说它__init__()没有运行,因为它没有看到 cookies 变量。我不明白这怎么可能。如果不局限于 spynner 模块,有人可以大胆猜测 python 对象如何因这样的错误而失败?

编辑:我肯定会在这里粘贴我的代码,除了它不是全部在一个地方让我紧凑地展示它。我应该早点做,但这里是整体结构以及我如何实例化和使用 spynner。

# helper class to get url data
class C:
   def __init__(self):
       self.browser = spynner.Browser()

   def get_data(self, url):
       try:
           self.browser.load(url)
           return self.browser.html
       except:
           raise

# class that does other stuff among saving url data to disk
class B:
    def save_url_to_disk(self, url):
        urlObj = C()
        html = urlObj.get_data(url)
        # do stuff with html


# class that drives everything
class A:
    def do_stuff_and_save_url_data(self, url):
       fileObj = B()
       fileObj.save_url_to_disk(url)

driver = A()
# call this function for multiple URLs.
driver.do_stuff_and_save_url_data(url)

我的运行方式是——

# xvfb-run python myfile.py

段错误可能是我正在做的其他事情。可能是因为我使用的 xvfb 处理不当?我还不知道。我需要提一下,我对 python 比较陌生。

我注意到,当我使用“ http://www.google.com ”运行上面的代码时,我每隔一段时间就会出现段错误。

4

1 回答 1

0

的代码块do_stuff_and_save_url_data()不使用引用self
那么这个函数的执行不依赖于driver.

的代码块save_url_to_disk()也不使用引用self
那么第二个函数的执行不依赖于对象fileObj

只有代码块get_data()使用引用self,更准确地说是引用self.browser
所以它的执行和结果取决于类browser中实例的属性。这个属性实际上是一个以该类命名的浏览器实例。urlObjCbrowserspynner.Browser

最后,您只需使用spynner.Browser().html. 并且以任何方式创建driverfileObj都不是强制性的。

.

另一点是,
当指令driver.do_stuff_and_save_url_data(url)被执行时,
该方法driver.do_stuff_and_save_url_data(url)首先被创建,然后被执行,最后被“销毁”(或者更准确地说是在 RAM 中的某个地方忘记了),因为它没有被分配给任何标识符。

然后标识符fileObj,它是属于函数的本地命名空间的标识符,也丢失了,这意味着类driver.do_stuff_and_save_url_data()的实例fileObjB也丢失了,以备不时之需,因为它没有更多有效的分配标识符。

同理save_url_to_disk()
方法创建并执行后,classfileObj.save_url_to_disk(url)的对象urlObj丢失C,其中包含浏览器的实例(由创建的对象spynner.Browser()):创建的浏览器及其所有数据丢失。

我想知道这是否不是因为每次执行后都会破坏浏览器实例,do_stuff_and_save_url_data()并且save_url_to_disk()cookie信息不会在别有用心的调用之前被破坏。

.

因此,在我看来,您的代码仅在类的两个定义中嵌入了两个函数,A并且B它们被用作被视为函数,而不是作为方法。

1/ 我认为这不是一个好的编码模式。当一个人只想要简单的函数时,它们必须在任何类之外编写。

2/ 问题是,如果操作是由函数触发的,每次激活这些函数时都会创建一个新的浏览器,即使它们有方法的外衣。

你会说我希望这些函数与由spynny.Browser().
这就是为什么我认为它们不能像现在这样嵌入在类中的函数,而是附加到浏览器稳定实例的真实方法。对象的目的是将数据和处理数据的工具保存在同一个命名空间中。

-

.

说了这么多,我个人会写:

class C(spynner.Browser):
   def __init__(self):
       spynner.Browser.__init__(self)

   def get_data(self, url):
       try:
           self.html = self.load(url).html
       except:
           raise

    # method that does other stuff among saving url data to disk
    def save_url_to_disk(self, url):
        get_data(url)
        # do stuff with self.html

    # method that drives everything
    def do_stuff_and_save_url_data(self, url):
        self.save_url_to_disk(url)


driver = C()
driver.do_stuff_and_save_url_data(url)

但我不确定你是否完全了解了你的所有考虑,我警告说在阅读你的帖子之前我不知道 spynner。相对于您的实际问题,我所写的所有内容都可能是愚蠢的。请让评论家关注我的帖子。

于 2013-12-11T15:05:49.880 回答