【问题标题】:Get Deferred from dbpool.runQuery instead of data with Twisted and Oracle从 dbpool.runQuery 获取延迟,而不是使用 Twisted 和 Oracle 获取数据
【发布时间】:2016-10-04 16:57:56
【问题描述】:

我正在尝试使用 Twisted 和 runQuery 从 Oracle 获取一些数据,并不断获取 Deferred 而不是实际数据。 如何解决? 一些代码(我排除了一些不必要的部分,但思路应该很清楚):

from twisted.enterprise import adbapi
from twisted.internet import defer
import service_config

ORACLE_DSN = service_config.oracle_dsn
ORACLE_USER = service_config.oracle_user
ORACLE_PASSWORD = service_config.oracle_password
dbpool = adbapi.ConnectionPool('cx_Oracle',
    user=ORACLE_USER,
    password=ORACLE_PASSWORD,
    dsn=ORACLE_DSN, port='49161')

@defer.inlineCallbacks
def ask_db():
    data = yield dbpool.runQuery("SELECT * FROM customer")

a = ask_db()
print(a)

我让反应堆在其他模块中运行,如果这很重要的话。 提前谢谢你。

更新: 在@notorious.no 的帮助下,得到了工作代码,返回数据而不是 Python 3.5 的延迟:

@defer.inlineCallbacks
def ask_db(request):
    data = yield dbpool.runQuery(request)

    return defer.returnValue(data) 

【问题讨论】:

  • 您没有从 ask_db 函数返回任何内容。如果您将 print(a) 更改为 ask_db 中的 print(data),那么会发生什么?
  • 你的意思是 def ask_db(): data = yield dbpool.runQuery("SELECT * FROM customer") print(data)?如果是,则没有任何变化。

标签: python oracle twisted deferred


【解决方案1】:

你得到一个 Deferred 是因为你调用了一个总是返回 Deferred 的 inlineCallback。您还误解了 yield 的作用。它实际上并没有从inlinceCallback 返回值,它只是等待结果。使用 defer.returnValue() 返回一个值(如果您使用的是 Python 3.4+,则可以使用简单的 return)。你的代码应该是这样的:

from __future__ import print_function
#...

@defer.inlineCallbacks
def ask_db():
    data = yield dbpool.runQuery("SELECT * FROM customer")
    defer.returnValue(data)    # actually return a value

a = ask_db()    # this returns a Deferred so add callbacks!
a.addCallback(print)    # add a useful callback to processes query list
reactor.run()

你之前和这个答案的区别在于添加了一个回调,所以当runQuery()返回一个值时,回调被执行并且ask_db()实际上返回一个你关心的值。

参考文献

【讨论】:

  • 谢谢!我使用了 defer.returnValue(data) 和 a.addCallback(some other func) 但仍然是相同的结果。甚至更多 - addCallback 中的“其他一些函数”甚至没有启动,所以对我来说,yield 似乎停留在 Deferred 中并且不会更改为数据或失败。会不会是 ConnectionPool 没有真正连接到数据库?或者它必须返回一些ConnectionError?我忘了提,我使用的是 Python 3.5。而且我的反应堆在另一个模块中运行,那么是否需要将reactor.run()添加到这个模块中?
  • 当我说“我使用了 defer.returnValue(data) 和 a.addCallback(some other func) 但仍然是相同的结果。”我的意思是我在发布这个问题之前使用了它。我现在也尝试使用它。结果仍然被推迟。
  • 你在做print(a) 还是print(ask_db())?因为这不会给出查询结果,所以会打印 Deferred 对象。不知道为什么回调不启动,当你使用同步语法时会发生什么?当你运行 cx_Oracle.connect(user, pswd, dsn, port) 时会发生什么?
  • 看起来您的解决方案有效,但由于我在 ask_bd() 周围有很多同步逻辑,因此这些功能似乎是问题所在。我可以在我重写所有的东西后告诉我。谢谢!我也发现 ConnectionPool args 的小错误。 dsn 中必须有“IP:port”,而不是单独的“port=”。
  • 谢谢@notorious.no,在您的帮助下得到了工作代码!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-03
  • 2022-01-23
相关资源
最近更新 更多