【问题标题】:Real time python app that works on a database适用于数据库的实时 python 应用程序
【发布时间】:2017-05-24 04:24:45
【问题描述】:

我正在将 postgreSQL 与 python 一起使用,并且 SQL 数据库可以定期添加行。目前,python程序不知道是否添加了新数据(我使用psycopg2读取行。但它读取到行结束并停止)。如果添加了新数据,如何让我的 python 程序不断搜索?或者我可以让postgreSQL在添加新行时触发python?

这是我目前拥有的:

def get_data():
    try:
        connect = psycopg2.connect(database="yardqueue", user="postgres", password="abcd", host="localhost", port="5432")
    except:
        print "Could not open database"
    cur = connect.cursor()
    cur.execute("SELECT id,position FROM container")
    rows = cur.fetchall()
    for row in rows:
        print "ID = ", row[0]
        print "Position = ", row[1]

如您所见,当我运行它时,一旦变量“行”到达最后一行,它就会停止。

编辑:有没有办法让我的 python 代码运行一段指定的时间?如果是这样,我可以让它通过数据库,直到我杀死它。

【问题讨论】:

  • 为什么需要查明是否添加了新数据?
  • 试试 cursor.rowcount
  • @AzatIbrakov 因为,这是一个关于在院子里设置集装箱位置的项目。容器数据不断添加,我希望python为每个数据分配特定位置
  • @HaifengZhang 行数对于脚本的特定运行来说是恒定的,对吗?
  • 您可以使用time.sleep 进行无限循环并检查之前的行数是否发生了变化

标签: python database postgresql


【解决方案1】:

如果您想查看我们可以写入的新记录(假设container 表中没有删除):

from time import sleep

import psycopg2

IDLE_INTERVAL_IN_SECONDS = 2


def get_data():
    try:
        connect = psycopg2.connect(database="yardqueue", user="postgres",
                                   password="abcd", host="localhost",
                                   port="5432")
    except:
        print "Could not open database"
        # TODO: maybe we should raise new exception? 
        # or leave default exception?
        return
    cur = connect.cursor()
    previous_rows_count = 0
    while True:
        cur.execute("SELECT id, position FROM container")
        rows_count = cur.rowcount
        if rows_count > previous_rows_count:
            rows = cur.fetchall()
            for row in rows:
                print "ID = ", row[0]
                print "Position = ", row[1]
            previous_rows_count = rows_count
        sleep(IDLE_INTERVAL_IN_SECONDS)

如果我们只想处理新记录,我们可以添加ordering by id 和offset like

from time import sleep

import psycopg2

IDLE_INTERVAL_IN_SECONDS = 2


def get_data():
    try:
        connect = psycopg2.connect(database="yardqueue", user="postgres",
                                   password="abcd", host="localhost",
                                   port="5432")
    except:
        # TODO: maybe we should raise new exception? 
        # or leave default exception?
        print "Could not open database"
        return
    cur = connect.cursor()
    rows_count = 0
    while True:
        cur.execute("SELECT id, position FROM container "
                    # sorting records by id to get new records data
                    # assuming that "id" column values are increasing for new records
                    "ORDER BY id "
                    # skipping records that we have already processed
                    "OFFSET {offset}"
                    .format(offset=rows_count))
        rows_count = cur.rowcount
        if rows_count > 0:
            rows = cur.fetchall()
            for row in rows:
                print "ID = ", row[0]
                print "Position = ", row[1]
        sleep(IDLE_INTERVAL_IN_SECONDS)

【讨论】:

  • 是的。 id 是主键
【解决方案2】:

不幸的是,数据库没有插入顺序的概念,因此您作为设计者必须提供明确的顺序。否则,您获取的行的顺序(使用新游标)可能随时更改。

这里一种可能的方法是在您的表中有一个serial 字段。 PostgreSQL 通过 sequence 实现了一个序列字段,它保证每个新插入的行都获得一个大于所有当前存在的序列号的序列号。但是:

  • 如果交易需要序列号并被中止,则可能存在漏洞
  • 如果多个并发事务插入一个串行字段,串行字段的顺序将是 insert 命令的顺序,而不是 commit 命令的顺序。这意味着竞争条件可能导致错误的顺序。但是,如果您在数据库中只有一位作家,那也没关系

另一种方法是使用插入日期字段 - 插入应用程序必须明确管理它,或者您可以使用触发器来透明地设置它。 PostgreSQL 时间戳具有微秒精度。这意味着如果同时插入许多行,则它们可以具有相同的插入日期值。您的 Python 脚本应该在打开游标之前读取时间并获取插入时间大于其上次运行时间的所有行。但是在这里你应该再次关心比赛条件......

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-09-11
    • 1970-01-01
    • 2014-08-03
    • 2017-12-20
    • 2020-06-13
    • 2020-02-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多