[英]SQLAlchemy core - how to make a ResultProxy case-insensitive wrt Schema column names?
[英]SQLAlchemy - How to access column names from ResultProxy and write to CSV headers
我正在嘗試使用SQLAlchemy建立與PostgreSQL數據庫的連接,執行SQL查詢並將文件的輸出打印到Linux中的文件。
from sqlalchemy import create_engine
import yaml
import csv
outfile = open('/path/filename.csv', 'wb')
outcsv = csv.writer(outfile, delimiter='\t')
with open('config.yml') as f:
cfg = yaml.safe_load(f)
username = cfg['credentials']['username']
password = cfg['credentials']['password']
host = cfg['credentials']['host']
port = cfg['credentials']['port']
dbname = cfg['credentials']['dbname']
engine = create_engine('postgresql://{}:{}@{}:{}/{}'.format(username, password, host, port, dbname))
result = engine.execute("""select * from db.tablename """)
# dump column titles (optional)
outcsv.writerow(x[0] for x in result.description)
# dump rows
outcsv.writerows(result.fetchall())
outfile.close()
但是,我收到以下錯誤消息-Traceback(最近一次調用): AttributeError中的文件“”,第12行:“ ResultProxy”對象沒有屬性“ description”
如果注釋以下命令,則可以成功獲取查詢結果,但沒有標題。 outcsv.writerow(x [0]對於x在result.description中)
經過研究,我發現方法-result._metadata.keys可以生成標頭。 但是,它以某種形式生成列表,我無法將其附加為標題。
請告知是否有任何方法可以將文件頭以及數據獲取到csv文件中。 在回答以上問題時,請考慮我是Python的初學者的事實。
在示例的這一行中:
result = engine.execute("""select * from db.tablename """)
變量result
指向類sqlalchemy.engine.ResultProxy
的實例。
您想要獲取列名稱以寫入到csv文件的第一行,並通過檢查result
對象找到result._metadata.keys
來返回常規的python列名稱list
。
Python中的一個約定是,只要對象的屬性,變量或方法前面帶有下划線(例如_metadata
),這意味着它不打算成為公共API,並且程序包的維護者可以以這種方式更改其實現。如果您依賴這些東西,則會破壞您的代碼(但是,對於穩定的庫(如SQLAlchemy)來說不太可能)。 幸運的是,在這種情況下,有一個文檔化的公共API供您獲取所需的內容: ResultProxy.keys()
。
請記住,您的result
變量指向ResultProxy
實例,因此您可以訪問該實例上的keys()
方法以獲取列名,例如:
result.keys()
當我們嘗試寫入您的csv文件時會發生什么:
outcsv.writerow(result.keys())
我們得到以下異常:
TypeError: a bytes-like object is required, not 'str'
我將假設您在說這句話時指的是:
但是,它以某種形式生成列表,我無法將其附加為標題。
您可以看一下open()
API,但是問題在於您以一種期望二進制數據的方式打開了文件,而不是從result.keys()
返回的字符串。 因此,如果我們將打開文件的行更改為:
outfile = open('/path/filename.csv', 'w')
outfile.writerow
將接受result.keys()
的結果。
其他一切都應該“正常工作”。
這是我用來測試的代碼:
import csv
from sqlalchemy import Column, Integer, String, create_engine
from sqlalchemy.orm import sessionmaker
from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()
engine = create_engine('sqlite:///:memory:', echo=False)
Session = sessionmaker(bind=engine)
class Model(Base):
__tablename__ = 'model'
id = Column(Integer, primary_key=True)
col1 = Column(String(10))
col2 = Column(String(10))
if __name__ == '__main__':
# create some test data
Base.metadata.drop_all(bind=engine)
Base.metadata.create_all(bind=engine)
s = Session()
data = dict(col1='a', col2='b')
s.add_all(Model(**data) for _ in range(5))
s.commit()
s.close()
# put the session away and work with the engine
result = engine.execute("select * from model")
outfile = open('filename.csv', 'w', newline='')
outcsv = csv.writer(outfile, delimiter='\t')
outcsv.writerow(result.keys())
outcsv.writerows(result.fetchall())
這是csv的內容:
id col1 col2
1 a b
2 a b
3 a b
4 a b
5 a b
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.