Python - 使用 sqlalchemy 的 Postgres 查询返回“空数据框”

Posted

技术标签:

【中文标题】Python - 使用 sqlalchemy 的 Postgres 查询返回“空数据框”【英文标题】:Python - Postgres query using sqlalchemy returns "Empty Dataframe" 【发布时间】:2020-06-02 11:06:59 【问题描述】:

我尝试从 postgres 数据库中查询一些数据并使用以下 Python 代码将结果添加到 excel 中(我通过 ssh 隧道连接到服务器并使用 sqlalchemy 连接到数据库):

from sshtunnel import SSHTunnelForwarder
from sqlalchemy.orm import sessionmaker 
from sqlalchemy import create_engine
import pandas as pd
from pandas import DataFrame
import xlsxwriter
import openpyxl

with SSHTunnelForwarder(
    ('<server_ip>', 22),
    ssh_username="<server_username>",
    ssh_private_key='<private_key_path>', 
    remote_bind_address=('localhost', 5432)) as server:
    server.start()
    print "server connected"

    #connect to DB
    local_port = str(server.local_bind_port)
    engine = create_engine('postgresql://<db_username>:<db_password>:' + local_port +'/<db_name>')
    Session = sessionmaker(bind=engine)
    s = Session()
    print 'Database session created'

    not_empty_query = False #flag empty queries
    arg_query = "SELECT * from portalpage where id not in (select entityid from sharepermissions where entitytype='PortalPage')"
    query = s.execute(arg_query)
    print(query)
    for row in query: #check if the query is empty
        if (row[0] > 0):
            not_empty_query = True
            break
    if not_empty_query == True: #if the query isn not empty add response into excel
        df = pd.DataFrame(pd.np.empty((0, 8)))
        df = DataFrame(query.fetchall())
        print(df)
        df.columns = query.keys()
        df.to_excel("out.xlsx", engine="openpyxl", sheet_name="Worksheet_Name")

s.close()

它适用于我尝试执行的大多数查询,但是对于上述查询,它会返回以下错误:

ValueError: Length mismatch: Expected axis has 0 elements, new values have 8 elements

在进行故障排除时,我打印了 df 参数并得到了一个“空数据框”。 但是,当我直接在我的数据库中运行相同的查询时,我会得到结果。

我还注意到,在响应中,在我的数据库中,有些列是空的(不确定是否有任何区别)。

还请找到代码执行的打印屏幕。

如果我删除下面的代码,上面将起作用:

for row in query: #check if the query is empty
    if (row[0] > 0):
        not_empty_query = True
        break
if not_empty_query == True:

但是,如果我删除了这个“for 循环”,那么对于其他查询(主要是返回空结果的查询)我会得到同样的错误。 请在下面找到一个示例。

有什么想法吗?

【问题讨论】:

使用@Spyros_av 的想法。首先将所有数据放入数据框中,然后推送到excel 正如我在下面回答的那样,即使我定义了一个空数据框,我仍然会遇到同样的错误。 你能分享更新的脚本吗?所以我们可以看看为什么它不起作用 我想确定您使用pd.DataFrame(pd.np.empty((0, 8))) 创建了一个空数据框来存放查询结果。这是@Spyros_av 建议的。 从你的脚本中删除这部分for row in query: #check if the query is empty if (row[0] &gt; 0): not_empty_query = True break 【参考方案1】:

请试试这个。我发现您用来检查查询是否返回任何数据的逻辑是问题所在。我已经对其进行了修改,以便首先进行检查。如果返回任何行,则它会构建数据框,然后导出到 excel。请让我知道它是否有效。

from sshtunnel import SSHTunnelForwarder
from sqlalchemy.orm import sessionmaker 
from sqlalchemy import create_engine
import pandas as pd
from pandas import DataFrame
import xlsxwriter
import openpyxl

with SSHTunnelForwarder(
    ('<server_ip>', 22),
    ssh_username="<server_username>",
    ssh_private_key='<private_key_path>', 
    remote_bind_address=('localhost', 5432)) as server:
    server.start()
    print "server connected"

    #connect to DB
    local_port = str(server.local_bind_port)
    engine = create_engine('postgresql://<db_username>:<db_password>:' + local_port +'/<db_name>')
    Session = sessionmaker(bind=engine)
    s = Session()
    print 'Database session created'
    arg_query = "SELECT * from portalpage where id not in (select entityid from sharepermissions where entitytype='PortalPage')"
    query = conn.execute(arg_query)##rows_count
    rows = query.fetchall()
    columns=query.keys()
    if len(rows) > 0:
        df = DataFrame(rows)
        df.columns =columns
        df.to_excel("out.xlsx", engine="openpyxl", sheet_name="Worksheet_Name")
    else:
        print "no data"

【讨论】:

我得到了同样的错误,我也注意到即使查询没有返回任何结果,它也会进入 if 子句,如果我在 if 子句之前打印查询变量,它会返回:@ 987654322@ 我想我找到了它是什么。我修改了脚本:query.fetchall()query.keys() 需要在循环之前存储它们的值。请再次检查。 是的,这似乎工作得很好。谢谢@MEdwin。【参考方案2】:

先尝试创建一个空的数据框。

if not_empty_query == True: #if the query isn not empty add response into excel
        df = pd.DataFrame(pd.np.empty((0, 8)))   
        df = DataFrame(query.fetchall())
        print(df)
        df.columns = query.keys()
        df.to_excel("out.xlsx", engine="openpyxl", sheet_name="Worksheet_Name")

【讨论】:

您好,感谢您的回复。我仍然得到同样的错误。理想情况下,我希望数据框具有动态大小,因为我将在函数中使用它并运行多个查询。

以上是关于Python - 使用 sqlalchemy 的 Postgres 查询返回“空数据框”的主要内容,如果未能解决你的问题,请参考以下文章

python web开发-flask中sqlalchemy的使用

python ORM - sqlalchemy 操作使用

Python中的SQLAlchemy

Python flask-sqlalchemy初级解析

Python sqlalchemy使用

python之sqlalchemy的使用