2012-02-28 52 views
14

我们正在尝试遵循PEP8格式化我们的Python代码并保持每行低于80个字符的指导原则。格式化SQLAlchemy代码

我们的SQLAlchemy行特别麻烦,有大量的链接方法和大量的复杂参数,逻辑和嵌套函数。

是否有任何特定的最佳实践来格式化Python SQLAlchemy的约束PEP8?

我发现的最接近的答案是here,但我所处理的代码远远更复杂。

回答

7

pep-8不鼓励反斜杠,但对于SQLAlchemy代码,我不禁想到它们是最可读的,因为您可以将每个生成函数保留在自己的行的开头。如果括号内有很多参数,我会在个别行上分解它们。

subkeyword = Session.query(
        Subkeyword.subkeyword_id, 
        Subkeyword.subkeyword_word 
      ).\ 
       filter_by(subkeyword_company_id=self.e_company_id).\ 
       filter_by(subkeyword_word=subkeyword_word).\ 
       filter_by(subkeyword_active=True).\ 
       one() 

当然不要紧代码是如何复杂的是它,压痕模式可以为任何代码量进行下去,但是在Python我们要避免过多的嵌套。通常在使用Query时,会发生嵌套,因为您正在组合许多子查询。因此,绝对提前构建子查询:

subq = Session.query(
       Bat.id, 
       func.foo(Bat.x, Bat.y).label('foo') 
       ).\ 
       filter(Bat.id==Bar.name).\ 
       correlate(Bar).\ 
       subquery() 

subq2 = Session.query(Foo.id, Foo.bar).\ 
       filter_by(flag>5).\ 
       subquery() 

result = Session.query(
        subq.c.id, 
        subq.c.foo, 
        subq2.c.bar 
       ).\ 
       join(subq2, 
        and_(
         subq.c.id > subq2.c.foo, 
         subq.bar == subq2.id 
        ) 
       ).\ 
       order_by(subq.c.id, subq2.c.bar) 

我会欢迎其他意见反斜杠的事情。

+2

pocoo团队风格指南中很好的反斜杠用法http://www.pocoo.org/internal/styleguide/ – estin 2012-02-28 12:04:59

1

是的,无论你做什么,这些都会变得很讨厌,所以如果你能把这些结构分成更短的行,那肯定是这样。

当你不能的时候,你可以通过把整个RHS放在一个圆括号中去掉所有的反斜杠。然后,Python将正确地解析多行构造,而不用反斜杠,但也很难说这是否更好。在这样的情况下,我认为你只需要用你最好的判断,抓住你的鼻子并投入。

+1

pep8有关反斜杠的说明的机会是什么(字面上,“这些应该优先使用反斜杠换行“)是唯一提及的)?如果他们不鼓励,为什么Python甚至拥有它们? – zzzeek 2012-02-28 19:45:50

2

我是类似于zzzeek在他的回答中指出的反斜杠的用户。 PEP8只是一个指导方针,当你违犯它时不要失眠!

不过,我也经常使用以下格式,在那里我已经偷zzzeek的第一个例子中的类型,轻度调整了它,并重新格式化:

q = Session.query(
    Subkeyword.subkeyword_id, 
    Subkeyword.subkeyword_word, 
) 
q = q.filter_by(subkeyword_company_id=self.e_company_id) # first filter 
q = q.filter_by(subkeyword_word=subkeyword_word) # 2nd filter 
q = q.filter_by(subkeyword_active=True) 

if filter_by_foo: 
    q = q.filter(Subkeyword.foo == True) 

# Run the query (I usually wrap in a try block)... 
subkeyword = q.one() 

反复重新分配到q起初似乎有点讨厌,但我已经完成了。性能影响实际上是零。这种方式的一大优势是,您可以在尾部注释和注释行中混合使用,以记录您的查询(正如我对上面的无用添加所做的那样)。用反斜杠链接线限制你在这里。

格式的这种方式与逻辑触发修改吨,嵌入式标量选择等

作为另一示例配制大量查询时,特别干净,我有一个相当大(> 150线)CTE查询我在SQLAlchemy中生成的混合逻辑,别名和标签(这对生成的查询的可读性来说非常重要)混合了这两种方法。它的一个严重降低(血肉模糊)版本开始像下面的东西:

cte_init = session.\ 
    query(
     child1.foo.label("child1_foo"), 
     sa.literal(1).label("indent"), # can comment on non-slashed lines 
     child2.bar.label("child2bar"), 
     #comments between non-slashed lines ok, too 
     sa.func.MAX(toplevel.baz).label("max_baz"), 
    ).\ 
    select_from(top_level).\ 
    join(child1, 
     child1.id == toplevel.fk_child1_id).\ 
    join(child2. 
     child2.id == toplevel.fk_child2.id).\ 
    filter(top_level.name == "bogus").\ 
    cte(name = "cte", recursive = True) 

if(use_filter_x): 
    cte_init = cte_init.filter_by(x = "whatever") 

# etc (no, the above doesn't make any sense)... 

在一般情况下,如果要确保新业务(如许多常见的SQL格式方案做)带领你行了,它保持很可读。不要害怕括号内的换行符。

+1

这也带来了额外的好处,它使得'pdb' a * lot *更容易调试!因为每个过滤器都有自己的声明! – exhuma 2014-02-24 10:20:47

24

来到这里,希望有一个更好的解决方案,但我想我更喜欢括号环绕方式:

subkeyword = (
    Session.query(
     Subkeyword.subkeyword_id, 
     Subkeyword.subkeyword_word 
    ) 
    .filter_by(subkeyword_company_id=self.e_company_id) 
    .filter_by(subkeyword_word=subkeyword_word) 
    .filter_by(subkeyword_active=True) 
    .one() 
) 

这是很好的和明确的,并且避免了可怕的反斜杠。