在您的示例的这一行中:
result = engine.execute("""select * from db.tablename """)
变量result
指向该类的一个实例sqlalchemy.engine.ResultProxy http://docs.sqlalchemy.org/en/latest/core/connections.html#sqlalchemy.engine.ResultProxy.
您想要将列名称写入 csv 文件的第一行,并通过检查您的result
找到物体result._metadata.keys
它返回一个常规的 pythonlist
列名称。
Python 中的一个约定是,只要对象上的属性、变量或方法都以下划线开头(例如_metadata
)这意味着它不打算成为公共 API,并且如果您依赖这些东西,包的维护者可能会以破坏您的代码的方式更改其实现(但是对于 SQLAlchemy 等稳定的库来说不太可能)。幸运的是,在这种情况下,有一个记录在案的公共 API 可供您获取所需的内容:ResultProxy.keys() http://docs.sqlalchemy.org/en/latest/core/connections.html#sqlalchemy.engine.ResultProxy.keys.
请记住,您的result
变量指向一个ResultProxy
实例,这样您就可以访问keys()
方法来获取列名称,例如:
result.keys()
当我们尝试写入您的 csv 文件时会发生什么:
outcsv.writerow(result.keys())
我们得到这个异常:
TypeError: a bytes-like object is required, not 'str'
我假设这就是您所说的:
但是,它以某种形式生成我无法附加的列表
标头。
你可以看看open() https://docs.python.org/3/library/functions.html#openAPI,但问题是您打开文件的方式需要二进制数据,而不是从返回的字符串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