【问题标题】:Python - How do I find out if an AppEngine GQL query returns anything?Python - 如何确定 AppEngine GQL 查询是否返回任何内容?
【发布时间】:2012-07-13 17:32:17
【问题描述】:

这可能是一个一般性的 Python 问题,而不是 AppEngine 特定的问题。我无法确定我的 Google AppEngine GQL 查询是否返回对象。 我是 AppEngine 和 python 的新手,所以这可能是一个简单的问题

我正在使用python代码:

user = db.GqlQuery("SELECT * FROM UserStore WHERE user_id = 1234567890")

为了检查是否有用户返回,我一直在尝试:

if(user in locals()):
  self.response.out.write('User Exists: ' + user.user_id)
  return
else:
  CreateTheUser()

但我现在认为这不是最好的方法。有没有更好的方法来判断db.GqlQuery 语句是否返回了用户(或用户列表)?

【问题讨论】:

  • if user in locals() 不符合您的预期,原因有几个。首先,检查locals() 将告诉您变量是否已定义——它总是如此,因为您刚刚分配给它。其次,您实际上是在检查用户变量的 value 是否作为本地键存在 - 您尝试做的应该是 if 'user' in locals():。例如,foo='hello'; foo in locals() 等价于'hello' in locals()not 等价于'foo' in locals()!

标签: python google-app-engine


【解决方案1】:

试试这个,如果查询没有返回任何内容,我认为user 的值将是None

if user is not None:      #or simply `if user`
    #do something
else:
    #do something else

【讨论】:

  • if user 在这种情况下绰绰有余。
  • 我不知道。我发现if user is not Noneif user 更明显、更易读。这只是口味问题,但并不总是越短越好。
  • 不,不是。 not None 仅检查它是否不是 NoneTypeif user 将评估为具有空字符串、空列表、空字典的 False...当然它比检查 NoneType 更通用,所以它取决于如何具体您要进行检查。
  • @aschmid00 如果用户是 ''(空字符串)怎么办?当然,这应该在模型定义等其他地方进行检查,但是明确是 python 禅宗建议的(在有选项时选择)。
【解决方案2】:

从你的例子

user = db.GqlQuery("SELECT * FROM UserStore WHERE user_id = 1234567890")

将始终返回一个查询对象,例如<google.appengine.ext.db.Query object at 0xab71f6c> .

要评估返回的结果,您需要使用 .get(), .fetch(), - run() 会为您提供 QueryIterator。

所以目前你的比较

user = db.GqlQuery("SELECT * FROM UserStore WHERE user_id = 1234567890")
if user:
  # do something

user = db.GqlQuery("SELECT * FROM UserStore WHERE user_id = 1234567890")
if user not None:
  # do something

将永远通过,因为用户永远不会是 None。

在这个特定示例中,您可能会使用user = db.GqlQuery("SELECT * FROM UserStore WHERE user_id = 1234567890").get(),因为您只期望一个结果。然后进行if user: 比较。

如果你使用 fetch() 你会得到一个列表。如果您想确认不超过一个用户存在,这可能很有用。 (不确定您如何管理对 user_id 的唯一约束,但这是一个单独的问题 ;-)

【讨论】:

    【解决方案3】:

    尝试使用try

    try:
        self.response.out.write('User Exists: ' + user.user_id) 
    except AttributeError:
        CreateTheUser()
    

    这种方法将尝试输出用户详细信息,如果用户对象的属性未定义,那么您将获得AttributeError。您还可以使用 Exception 捕获所有内置的、非系统退出的异常。

    EAFP:

    请求宽恕比请求许可更容易。这个常见的 Python 编码风格假定存在有效的键或属性,并且 如果假设被证明是错误的,则捕获异常。这个干净又快速 风格的特点是存在许多尝试和例外 陈述。该技术与许多人常见的 LBYL 风格形成鲜明对比 其他语言,例如 C。

    LBYL:

    在你跳跃之前先看看。这种编码风格明确测试 进行调用或查找之前的先决条件。这种风格对比 EAFP 方法的特点是存在许多如果 声明。

    在多线程环境中,LBYL 方法可能会带来风险 在“观看”和“跳跃”之间引入竞争条件。 比如代码,if key in mapping: return mapping[key] 可能会失败 如果另一个线程在测试之后但之前从映射中删除键 查找。可以使用锁或使用 EAFP 解决此问题 接近。

    【讨论】:

    • 你为什么要做try/except?这将是与Model.get_or_insert 的单一衬线,为什么不简单地if user?!
    • 如果存在属性可能会消失的风险,您需要locks 和/或try/except 子句。检查变量是否已定义就像您所说的if user 一样简单。但user.user_id 是所需的属性。
    • 我明白,但在这种情况下,很清楚,如果有一个用户,就有一个 user_id。如果您有可选属性,那么也许您是对的。在这种情况下,这对我来说真的不好看。对不起
    • 我认为这是我们必须同意不同意的一个。我非常愿意接受有关您意见的支持性信息。我认为@Tim Pietzcker 提供了一个很好的理由来使用:stackoverflow.com/a/1835844/879199。还有stackoverflow.com/questions/204308/…地址是哪一个。
    • 尝试 - except 块用于异常,而不是用于检查(合法)条件。此外,if-else 更易读、更简洁、更高效。
    猜你喜欢
    • 2015-04-23
    • 2013-04-08
    • 1970-01-01
    • 2011-05-22
    • 2010-09-17
    • 2011-03-13
    • 2012-04-14
    相关资源
    最近更新 更多