gpt4 book ai didi

python - 在模块导入时执行代码是否可以?

转载 作者:太空狗 更新时间:2023-10-29 18:04:03 24 4
gpt4 key购买 nike

我正在设计一个小型 GUI 应用程序来包装一个 sqlite 数据库(简单的 CRUD 操作)。我创建了三个 sqlalchemy 模型(m_personm_card.pym_loan.py,都在 /models 中文件夹)并且之前在每个文件夹的顶部都有以下代码:

from sqlalchemy import Table, Column, create_engine
from sqlalchemy import Integer, ForeignKey, String, Unicode
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import backref, relation

engine = create_engine("sqlite:///devdata.db", echo=True)
declarative_base = declarative_base(engine)
metadata = declarative_base.metadata

这感觉有点不对(DRY)所以建议我将所有这些东西移到模块级别(到 models/__init__.py)。

from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
from sqlalchemy import Table, Column, Boolean, Unicode
from settings import setup

engine = create_engine('sqlite:///' + setup.get_db_path(), echo=False)
declarative_base = declarative_base(engine)
metadata = declarative_base.metadata

session = sessionmaker()
session = session()

..并像这样导入declarative_base:

from sqlalchemy import Table, Column, Unicode
from models import declarative_base


class Person(declarative_base):
"""
Person model

"""
__tablename__ = "people"

id = Column(Unicode(50), primary_key=True)
fname = Column(Unicode(50))
sname = Column(Unicode(50))

但是我收到了很多反馈,说像这样在模块导入时执行代码是不好的吗? 我正在寻找关于正确方法的明确答案,因为它似乎通过尝试删除代码重复我引入了一些其他不良做法。任何反馈都会非常有用。

(为了完整性,下面是 settings/setup.py 中的 get_db_path() 方法,因为它在上面的 models/__init__ 中被调用。 py 代码。)

def get_db_path():

import sys
from os import makedirs
from os.path import join, dirname, exists
from constants import DB_FILE, DB_FOLDER

if len(sys.argv) > 1:
db_path = sys.argv[1]
else:
#Check if application is running from exe or .py and adjust db path accordingly
if getattr(sys, 'frozen', False):
application_path = dirname(sys.executable)
db_path = join(application_path, DB_FOLDER, DB_FILE)
elif __file__:
application_path = dirname(__file__)
db_path = join(application_path, '..', DB_FOLDER, DB_FILE)

#Check db path exists and create it if not
def ensure_directory(db_path):
dir = dirname(db_path)
if not exists(dir):
makedirs(dir)

ensure_directory(db_path)

return db_path

最佳答案

一些流行的框架(Twisted 就是一个例子)在导入时执行大量的初始化逻辑。能够动态构建模块内容的好处是有代价的,其中之一是 IDE 不能总是决定模块“中”有什么。

在您的特定情况下,您可能需要重构,以便在导入时不提供特定引擎,而是稍后提供。您可以在导入时创建元数据和您的 declarative_base 类。然后在开始时,在定义所有类之后,您调用 create_engine 并将结果绑定(bind)到您的 sqlalchemy.orm.sessionmaker。但如果您的需求很简单,您甚至可能不需要走那么远。

总的来说,我会说这不是 Java 或 C。除了定义函数、类和常量之外,没有理由害怕在模块级别做事。无论如何,您的类都是在应用程序启动时创建的,一个接一个。在我看来,对类进行一些小的猴子修补(在同一个模块中!)或创建一个或两个全局查找表是可以的如果它简化了您的实现

我绝对要避免的是模块中的任何代码导致导入顺序对您的用户很重要(除了简单提供要使用的逻辑的正常方式),或者修改模块外部代码的行为.然后你的模块变成黑魔法,这在 Perl 世界中被接受(ala use strict;),但我发现它不是“pythonic”。

例如,如果您的模块在导入时修改了 sys.stdout 的属性,我认为应该将行为转移到用户可以调用或不调用的函数中。

关于python - 在模块导入时执行代码是否可以?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9486345/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com