2012-02-28 23 views
14

Estamos tratando de seguir las pautas PEP8 para formatear nuestro código Python y mantenernos por debajo de 80 caracteres por línea.Formateo del código SQLAlchemy

Nuestras líneas SQLAlchemy son particularmente problemáticas, tienen muchos métodos encadenados y toneladas de parámetros complejos, lógica y funciones anidadas.

¿Existen algunas prácticas recomendadas para formatear Python SQLAlchemy con las limitaciones de PEP8?

La respuesta más cercana que he encontrado es here, pero el código que estoy tratando es mucho, mucho más complicado.

Respuesta

7

pep-8 desalienta las barras diagonales inversas, pero para el código SQLAlchemy no puedo evitar pensar que son las más legibles, ya que puede mantener cada función generativa al comienzo de su propia línea. Si hay muchos argumentos dentro del paréntesis, también los dividiré en líneas individuales.

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() 

que, por supuesto, no importa lo complicado que es el código, el patrón de sangrado se puede llevar en cualquier cantidad de código, sin embargo en Python que queremos que no se peguen excesiva. Por lo general, con Query, la anidación se produce porque estás componiendo muchas subconsultas juntas. Así que definitivamente construye las subconsultas antes de tiempo:

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) 

Me gustaría recibir otras opiniones sobre la barra invertida.

+2

uso de barras diagonales buenas en la guía de estilo de equipo de pocoo http://www.pocoo.org/internal/styleguide/ – estin

1

Sí, estos van a ser desagradables sin importar lo que hagas, por lo tanto, en la medida en que puedas dividir estos constructos en líneas más cortas, definitivamente hazlo.

Cuando no pueda, probablemente pueda deshacerse de todas esas barras inclinadas poniendo todo el RHS entre paréntesis. Python analizará las construcciones multilínea correctamente sin las barras diagonales inversas, pero también es difícil decir si es mejor o no. En casos como estos, creo que solo tiene que usar su mejor criterio, sostener la nariz y sumergirse.

+1

¿Cuáles son las posibilidades de que pep8 se aclare con respecto a las barras diagonales inversas (literalmente, "se deben usar con preferencia al uso de una barra inversa para continuación de línea. "es la única mención)? Si están desanimados, ¿por qué Python los tiene? – zzzeek

2

Soy un usuario frecuente de las barras invertidas de forma similar a lo que indicó zzzeek en su respuesta. PEP8 es solo una guía, ¡no pierdas el sueño cuando la violas!

Sin embargo, también utilizo con frecuencia el tipo de formato de abajo, donde he robado primer ejemplo de zzzeek, ​​ligeramente retocado, y reordenada:

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() 

La reasignación repetida a q parece un poco desagradable al principio , pero lo he superado. El impacto en el rendimiento es efectivamente nulo. Una gran ventaja de esta forma es que puede mezclar los comentarios finales y las líneas de comentarios para documentar sus consultas (como ya he hecho con las adiciones inútiles que aparecen arriba). Encadenar líneas con barras invertidas te limita aquí.

Esta forma de formato es particularmente limpia cuando la formulación de consultas masivas con toneladas de modificaciones de lógica-triggered, selecciona escalares integrados, etc.

Como otro ejemplo, tengo una bastante grandes (> 150 líneas) CTE consulta I Estoy generando en SQLAlchemy que tiene una gran cantidad de lógica mixta, alias y etiquetado (que es esencial para la legibilidad de la consulta generada) que mezcla ambos métodos.Una versión seriamente reducida (y mutilado) de que comience algo, como a continuación:

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)... 

En general, si se asegura de llevar sus líneas con las nuevas operaciones (como muchos esquemas de formato SQL común no), se mantiene bastante legible Tampoco le tengas miedo a las nuevas líneas entre corchetes.

+1

¡Esto también tiene la ventaja añadida de que hace que la depuración con 'pdb' a * lot * sea más fácil! ¡Porque cada filtro está en su propia declaración! – exhuma

24

Vine aquí con la esperanza de una solución mejor, pero creo que prefiero el estilo de ajuste paréntesis:

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() 
) 

Ésta es agradable y claro, y evita la temida barra invertida.