isinstance() 返回False,原因未知。

4
所以,情况如下:
我正在使用GAE Pipeline库进行流程控制,我的类FanoutPipeline是从该库的Pipeline类派生而来的:
from pipeline import pipeline
class FanoutPipeline(pipeline.Pipeline):

当管道过程运行时,它会进行检查以验证对象实际上是从Pipeline派生的类的实例,但它返回False:

  yielded = pipeline_iter.send(next_value)
  # here I check that yielded is an object of `FanoutPipeline`
  # class, plz see logs output below
  if isinstance(yielded, Pipeline):  # returns false here

我添加了大量的日志来获取类树和它们的模块:

  import inspect
  logging.debug('Yielded: {}'.format(yielded))
  for cls in inspect.getmro(yielded.__class__):
      logging.debug('Yielded base: {}'.format(inspect.getmodule(cls)))
      logging.debug('Yielded base: {}'.format(cls))
  logging.debug('PipelineMeta classes: {}'.format(_PipelineMeta._all_classes))
  logging.debug('Pipeline: {}'.format(Pipeline))
  logging.debug('Pipeline module: {}'.format(inspect.getmodule(Pipeline)))
  for cls in inspect.getmro(Pipeline):
    logging.debug(inspect.getmodule(cls))
  if isinstance(yielded, Pipeline):

并获得了以下输出:

D 21:55:48.079 Yielded: project.handlers.pipeline_gcm.FanoutPipeline(*(None, {u'campaign_id': u'xxx', u'campaign_name': u'xmas notification', u'execution': {u'action': u'market', u'conditions': {u'delayBetweenNotificationsHours': 0, u'in... (515 bytes), **{})
D 21:55:48.079 Yielded base: <module 'project.handlers.pipeline_gcm' from '/base/data/home/apps/s~project-dev3/9.389913797024223872/projects/handlers/pipeline_gcm.pyc'>
D 21:55:48.079 Yielded base: <class 'project.handlers.pipeline_gcm.FanoutPipeline'>
D 21:55:48.080 Yielded base: <module 'pipeline.pipeline' from '/base/data/home/apps/s~project-dev3/9.389913797024223872/libraries/pipeline/pipeline.pyc'>
D 21:55:48.080 Yielded base: <class 'pipeline.pipeline.Pipeline'>
D 21:55:48.080 Yielded base: <module '__builtin__' (built-in)>
D 21:55:48.080 Yielded base: <type 'object'>
D 21:55:48.081 PipelineMeta classes: [<class 'libraries.pipeline.pipeline.Pipeline'>]
D 21:55:48.081 Pipeline: <class 'libraries.pipeline.pipeline.Pipeline'>
D 21:55:48.081 Pipeline module: <module 'libraries.pipeline.pipeline' from '/base/data/home/apps/s~project-dev3/9.389913797024223872/libraries/pipeline/pipeline.pyc'>
D 21:55:48.082 <module 'libraries.pipeline.pipeline' from '/base/data/home/apps/s~project-dev3/9.389913797024223872/libraries/pipeline/pipeline.pyc'>
D 21:55:48.082 <module '__builtin__' (built-in)>

你看到了,yielded在基类中明显有 pipeline.pipeline.Pipeline,模块路径相匹配。

以下是可能的原因: 1. 对象在进程之间以某种方式传递,在一个进程中加载了一个基类,在另一个进程中加载了另一个基类,因此检查失败。 2. 相对路径存在差异,即对象在创建时所在的进程中具有 pipeline.pipeline 模块,而在使用它并执行 isinstance 检查的进程中具有 libraries.pipeline.pipeline 模块。

请帮我解决这个问题好吗?我应该首先尝试什么?是什么原因导致这种失败?


1
type(yielded) 返回什么? - Kaustav Datta
1
@KaustavDatta 产生了类型:<class 'project.handlers.pipeline_gcm.FanoutPipeline'>。 - Andrew_Lvov
3
我猜测...你正在导入两个版本的类,一个是libraries.pipeline.pipeline.Pipeline,另一个是pipeline.pipeline.Pipeline。这意味着你在sys.path中有/base/data/home/apps/s~project-dev3/9.389913797024223872//base/data/home/apps/s~project-dev3/9.389913797024223872/libraries。你不应该在Python路径中有/base/data/home/apps/s~project-dev3/9.389913797024223872/,也不应该导入libraries.anything - tdelaney
1
@tdelaney非常感谢,我将from pipeline.pipeline替换为from libraries.pipeline.pipeline,其中声明了FanoutPipeline类,问题得到解决。 您能否将您的评论移动到答案中,这样我就可以选择它作为解决方案了吗? - Andrew_Lvov
1个回答

3
您正在导入两个版本的类,一个为libraries.pipeline.pipeline.Pipeline,另一个为pipeline.pipeline.Pipeline。这意味着您在sys.path中拥有/base/data/home/apps/s~project-dev3/9.389913797024223872//base/data/home/apps/s~project-dev3/9.389913797024223872/libraries。尽管您知道它们只是指向同一个模块的两个路径,但Python并不知道,会将它们视为两个不同的类。
您需要决定是否要基于librarieslibraries内部的各种模块来进行导入,并始终一致地编写您的导入内容。您还应该停止将“未选择”的目录添加到sys.path中,以便以错误的方式导入模块失败。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接