如何运行 sqlacodegen?

How to run sqlacodegen?

我正在尝试 运行 sqlacodegen 从现有的 PostgreSQL 数据库创建 SQLAlchemy 模型。

不会运行。当我输入 sqlacodegen --help 时,我得到:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: bad operand type for unary -: '_Helper'

基本说明是here

如何将 sqlacodegen 获取到 运行?

因为你在 Python shell:

>>> import sqlacodegen
>>> sqlacodegen --help
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: bad operand type for unary -: '_Helper'

您应该在 Unix 命令 shell / Windows 命令提示符中执行 sqlacodegen --help:

% sqlacodegen --help
usage: sqlacodegen [-h] [--version] [--schema SCHEMA] [--tables TABLES]
                   [--noviews] [--noindexes] [--noconstraints] [--nojoined]
                   [--noinflect] [--outfile OUTFILE]
                   [url]

Generates SQLAlchemy model code from an existing database.

positional arguments:
  url                SQLAlchemy url to the database

optional arguments:
  -h, --help         show this help message and exit
  --version          print the version number and exit
  --schema SCHEMA    load tables from an alternate schema
  --tables TABLES    tables to process (comma-separated, default: all)
  --noviews          ignore views
  --noindexes        ignore indexes
  --noconstraints    ignore constraints
  --nojoined         don't autodetect joined table inheritance
  --noinflect        don't try to convert tables names to singular form
  --outfile OUTFILE  file to write output to (default: stdout)

实际命令的示例是:

% sqlacodegen --outfile models.py \
postgresql://gollyjer:swordfish@localhost:5432/mydatabase

其中 gollyjer:swordfish 是格式为 user:password 的凭据。

这里已经回答了一些问题:

  1. sqlacodegen 应该使用 pip 安装
  2. 一旦安装,它应该是 运行 来自 windows 命令提示符而不是来自 python shell。
  3. 如果您提供多个 table 名称,请不要在 table 名称之间提供任何 space,仅提供逗号。

正如@Antti 所建议的,应该从命令 shell.

使用 sqlacodegen

无论如何,可以使用 CodeGenerator class 和 SqlAlchemy:

将代码生成嵌入到您自己的代码中
import io
import sys
from sqlalchemy import create_engine, MetaData
from sqlacodegen.codegen import CodeGenerator

def generate_model(host, user, password, database, outfile = None):
    engine = create_engine(f'postgresql+psycopg2://{user}:{password}@{host}/{database}')
    metadata = MetaData(bind=engine)
    metadata.reflect()
    outfile = io.open(outfile, 'w', encoding='utf-8') if outfile else sys.stdout
    generator = CodeGenerator(metadata)
    generator.render(outfile)

if __name__ == '__main__':
    generate_model('database.example.org', 'dbuser', 'secretpassword', 'mydatabase', 'db.py')

这将在 db.py 文件中创建数据库模型。

这就是我让它工作的方式。在 Python 中创建虚拟环境并在 shell(bash、终端)中激活它。 创建一个 env_file.env 应该像这样填充:

DB_NAME=x
DB_USER=y
DB_PASS=z
DB_HOST=MY_HOST.com
DB_PORT=3306 (default, or take your port)
SCHEMA_NAME=a
TABLE_NAMES=b,c,d
FULL_PATH=./test

和运行

source env_file.env
# check:
echo $DB_PORT
# Should give you 3306

然后运行:

pip install pymysql
pip install sqlacodegen

sqlacodegen mysql+pymysql://$DB_USER:$DB_PASS@$DB_HOST:$DB_PORT/$DB_NAME?charset=utf8 --schema $SCHEMA_NAME --tables $TABLE_NAMES --outfile $FULL_PATH

您将在您的文件夹中看到一个新文件“test”,其中包含您可以从表“b”、“c”和“d”中获得的所有信息。

输出模式如下:

# coding: utf-8
from sqlalchemy import CHAR, Column, DateTime, Float, Index, String, TIMESTAMP, text
from sqlalchemy.dialects.mysql import CHAR, INTEGER, LONGTEXT, MEDIUMINT, MEDIUMTEXT, TINYINT, VARCHAR
from sqlalchemy.ext.declarative import declarative_base

Base = declarative_base()
metadata = Base.metadata


class Trip(Base):
    __tablename__ = 'trips'
    __table_args__ = (
        Index('id', 'p_id', 'trip_name', 'update_time'),
        {'schema': 'holiday', 'comment': 'InnoDB free: 1234 kB; (`t_id`) REFER `holiday/prices'}
    )

    id = Column(INTEGER(11), primary_key=True)
    p_id = Column(INTEGER(11), nullable=False)
    trip_name = Column(String(150, 'utf8_unicode_ci'), nullable=False, server_default=text("''"))
    update_time = Column(DateTime, index=True)



class Prices(Base):
    __tablename__ = 'prices'
    __table_args__ = (
        Index('t_id'),
        Index('update_time'),
        {'schema': 'holiday', 'comment': 'InnoDB free: 1234 kB; (`t_id`) REFER `holiday/trips'}
    )

    id = Column(INTEGER(11), nullable=False, index=True, server_default=text("'0'"))
    t_id = Column(INTEGER(11), nullable=False, index=True, server_default=text("'0'"))
    company_name = Column(String(150, 'utf8_unicode_ci'), nullable=False, server_default=text("''"))
    update_time = Column(TIMESTAMP, index=True)