Maneira pitônica de criar uma longa cadeia de várias linhas

1307

Eu tenho uma consulta muito longa. Eu gostaria de dividi-lo em várias linhas em Python. Uma maneira de fazer isso em JavaScript seria usar várias frases e juntá-las a um +operador (eu sei, talvez não seja a maneira mais eficiente de fazer isso, mas não estou realmente preocupado com o desempenho nesta fase, apenas com a legibilidade do código) . Exemplo:

var long_string = 'some text not important. just garbage to' +
                  'illustrate my example';

Eu tentei fazer algo semelhante em Python, mas não funcionou, então eu costumava \dividir a cadeia longa. No entanto, não tenho certeza se essa é a única / melhor / pitônica maneira de fazê-lo. Parece estranho. Código atual:

query = 'SELECT action.descr as "action", '\
    'role.id as role_id,'\
    'role.descr as role'\
    'FROM '\
    'public.role_action_def,'\
    'public.role,'\
    'public.record_def, '\
    'public.action'\
    'WHERE role.id = role_action_def.role_id AND'\
    'record_def.id = role_action_def.def_id AND'\
    'action.id = role_action_def.action_id AND'\
    'role_action_def.account_id = ' + account_id + ' AND'\
    'record_def.account_id=' + account_id + ' AND'\
    'def_id=' + def_id
Pablo Mescher
fonte
207
Como o seu exemplo parece um bloco SQL apenas aguardando um ataque de injeção, outra sugestão é procurar uma biblioteca SQL de nível superior como SQLAlchemy ou algo para evitar hackers SQL brutos como este. (Talvez off-topic, mas você pediu "Todas as sugestões";.)
John Gaines Jr.
6
Esta é a "maneira Pythonic de criar código de várias linhas para uma cadeia longa" Para criar uma cadeia contendo novas linhas, consulte textwrap.dedent .
Bob Stein
8
@cezar Eu escrevi essa pergunta há mais de cinco anos, mas lembro que ela surgiu de não saber como colocar corretamente a longa consulta sql em várias linhas. Concordo que estava fazendo coisas estúpidas com essa longa sequência, mas essa não era minha pergunta e não era inteligente o suficiente para procurar um exemplo melhor para ilustrá-lo que não incluísse algumas preocupações com a injeção de sql.
Pablo Mescher 23/01
@cezar não, este não é um problema XY, a consulta seria melhor formatada em várias linhas em qualquer caso. O SQLi não está relacionado à questão em questão. Avisos corajosas grandes, porém, são totalmente justificado :)
bugmenot123
Eu escrevi um pequeno pacote para isso. Exemplo aqui: stackoverflow.com/a/56940938/1842491
Shay

Respostas:

2229

Você está falando sobre cadeias de linhas múltiplas? Fácil, use aspas triplas para iniciá-las e finalizá-las.

s = """ this is a very
        long string if I had the
        energy to type more and more ..."""

Você também pode usar aspas simples (3 delas no início e no final) e tratar a sequência resultante scomo qualquer outra sequência.

NOTA : Assim como em qualquer string, qualquer coisa entre as aspas inicial e final torna-se parte da string, portanto, este exemplo tem um espaço em branco à esquerda (conforme indicado por @ root45). Essa sequência também conterá espaços em branco e novas linhas.

Ou seja:

' this is a very\n        long string if I had the\n        energy to type more and more ...'

Finalmente, também é possível construir longas filas em Python assim:

 s = ("this is a very"
      "long string too"
      "for sure ..."
     )

que não incluirá espaços em branco extras ou novas linhas (este é um exemplo deliberado que mostra em que resultado o efeito de pular espaços em branco):

'this is a verylong string toofor sure ...'

Não são necessárias vírgulas, basta colocar as cadeias a serem unidas entre parênteses e certifique-se de levar em conta quaisquer espaços em branco e novas linhas necessários.

Levon
fonte
8
Eu prefiro usar explicitamente o operador "+" para o segundo método. Não é um aborrecimento e melhora a legibilidade.
Marco Sulla
38
@LucasMalor As strings adjacentes são uma concatenação em tempo de compilação. O uso do +operador não faz a concatenação acontecer em tempo de execução?
Joshua Taylor
13
Para referência, aqui estão os documentos oficiais para esse fenômeno: docs.python.org/2/reference/… (python 2) e docs.python.org/3/reference/… (python 3)
neverendingqs
4
Seu exemplo é bom, mas eu gostaria que ele tivesse incluído a demonstração de como incorporar com segurança dados variáveis ​​à consulta. O código de exemplo OP e @jessee mostra como NÃO fazer isso corretamente (eles são convites para ataques SQL). Veja também: dev.mysql.com/doc/connector-python/en/…
Scott Prive
2
você pode usar textwrap.dedentpara remover espaços em branco indesejados. docs.python.org/3/library/textwrap.html#textwrap.dedent
Corey Goldberg
190

Se você não deseja uma sequência de linhas múltiplas, mas apenas possui uma cadeia de linhas única longa, pode usar parênteses, mas não incluir vírgulas entre os segmentos da sequência, será uma tupla.

query = ('SELECT   action.descr as "action", '
         'role.id as role_id,'
         'role.descr as role'
         ' FROM '
         'public.role_action_def,'
         'public.role,'
         'public.record_def, '
         'public.action'
         ' WHERE role.id = role_action_def.role_id AND'
         ' record_def.id = role_action_def.def_id AND'
         ' action.id = role_action_def.action_id AND'
         ' role_action_def.account_id = '+account_id+' AND'
         ' record_def.account_id='+account_id+' AND'
         ' def_id='+def_id)

Em uma instrução SQL como a que você está construindo, cadeias de linhas múltiplas também seriam boas. Mas se o espaço em branco extra que uma sequência multilinha contiver seria um problema, seria uma boa maneira de conseguir o que você deseja.

Jesse
fonte
1
@Pablo você pode até mesmo adicionar comentários após o,
Ashwini Chaudhary
@ 200OK você quer dizer depois '?
usar o seguinte
3
Outra maneira de formatar essa string seria adicionar .format(...)após o parêntese de fechamento. %notação formatação deve trabalhar também, mas eu não tentei
kon psych
3
Observe que cada linha deve terminar com uma constante de cadeia de caracteres, portanto ' foo '+variable, não funcionará, mas ' foo '+variable+''funcionará.
yoyo
46
Este exemplo é uma porta aberta para ataques de injeção SQL. Por favor, ninguém use isso em nenhum aplicativo público. Consulte os documentos do MySQL para saber como usar 'espaços reservados': dev.mysql.com/doc/connector-python/en/…
Scott Prive
138

Quebrar linhas por \obras para mim. Aqui está um exemplo:

longStr = "This is a very long string " \
        "that I wrote to help somebody " \
        "who had a question about " \
        "writing long strings in Python"
anfíbio
fonte
9
Eu preferiria quer a notação citação triplo ou dentro de embrulho () para o caractere \
Khanh Hua
15
Aconselho vivamente a colocar os espaços no início das linhas seguintes, em vez de no final das linhas seguintes. Dessa forma, uma falta acidental é muito mais óbvia (e, portanto, é menos provável que isso aconteça).
Alfe
Também funciona com variáveis ​​no final das linhaslongStr = "account: " + account_id + \ ...
frmbelz
Estou recebendo o seguinte erro: the backslash is redundant between bracketsquando escrevi no interiorprint()
alper
50

Fiquei feliz com este:

string = """This is a
very long string,
containing commas,
that I split up
for readability""".replace('\n',' ')
Eero Aaltonen
fonte
32
Discordo. E se a primeira linha ("string = ...") estiver fortemente recuada? Seria necessário remover as linhas a seguir para recuo zero, que parece feio no meio de um bloco recuado.
Xjcl
1
Bem, a maioria das minhas longas seqüências ocorre no nível do módulo, onde isso se encaixa perfeitamente. No seu caso, isso obviamente não seria a melhor solução.
Eero Aaltonen
1
Eu gosto dessa abordagem porque privilegia a leitura. Nos casos em que temos longas seqüências de caracteres, não há como ... Dependendo do nível de indentação em que você se encontra e ainda limitado a 80 caracteres por linha ... Bem ... Não há necessidade de dizer mais nada. Na minha opinião, os guias de estilo python ainda são muito vagos. Obrigado!
Eduardo Lucio
Isso seria tão feio se for usado em um módulo, eu tenho que também.replace('\t','')
alper
44

Descobri que, ao criar seqüências longas, você geralmente está fazendo algo como criar uma consulta SQL; nesse caso, é melhor:

query = ' '.join((  # note double parens, join() takes an iterable
    "SELECT foo",
    "FROM bar",
    "WHERE baz",
))

O que Levon sugeriu é bom, mas pode estar vulnerável a erros:

query = (
    "SELECT foo"
    "FROM bar"
    "WHERE baz"
)

query == "SELECT fooFROM barWHERE baz"  # probably not what you want
darkfeline
fonte
8
+1 Alivia o revisor de código de ter que verificar assiduamente o lado direito de cada linha quanto a espaço em branco inadequado . O OP cometeu esse erro várias vezes, conforme observado por @KarolyHorvath.
Bob Stein
2
Ao revisar cadeias multilinhas codificadas de maneira semelhante, eu exijo espaço em branco adequado na extremidade esquerda de cada linha para facilitar a confirmação.
Guarda-chuva
3
As revisões do código @ BobStein-VisiBone não devem ser sobre erros de sintaxe ou pequenos bugs como esse, mas sobre a substância. Se alguém está colocando um código para revisão que possui erros de sintaxe (e, portanto, não é executado nem em todas as situações), algo está seriamente errado. Não é difícil executar fiapos antes de se comprometer. Se a pessoa não notou que seu programa não funciona corretamente porque cometeu um erro tão óbvio, não deveria estar cometendo.
Charles Addis
1
@CharlesAddis acordados, as revisões de código devem ocorrer após métodos automatizados, como fiapos, realce de sintaxe, etc. No entanto, alguns bugs com falta de espaço em branco podem não ser detectados dessa maneira. Aproveite todas as vantagens razoáveis ​​na proteção contra bugs, eu sugiro.
Bob Stein
33

Você também pode concatenar variáveis ​​ao usar a notação "" ":

foo = '1234'

long_string = """fosdl a sdlfklaskdf as
as df ajsdfj asdfa sld
a sdf alsdfl alsdfl """ +  foo + """ aks
asdkfkasdk fak"""

EDIT: Encontrei uma maneira melhor, com parâmetros nomeados e .format ():

body = """
<html>
<head>
</head>
<body>
    <p>Lorem ipsum.</p>
    <dl>
        <dt>Asdf:</dt>     <dd><a href="{link}">{name}</a></dd>
    </dl>
    </body>
</html>
""".format(
    link='http://www.asdf.com',
    name='Asdf',
)

print(body)
gjgjgj
fonte
26

Essa abordagem usa:

  • apenas uma barra invertida para evitar um avanço de linha inicial
  • quase nenhuma pontuação interna usando uma cadeia de caracteres tripla entre aspas
  • retira o recuo local usando o módulo textwrap inspect
  • usos Python 3.6 formatado interpolação string ( 'f') para o account_ide def_idvariáveis.

Este caminho me parece o mais pitônico.

# import textwrap  # See update to answer below
import inspect

# query = textwrap.dedent(f'''\
query = inspect.cleandoc(f'''
    SELECT action.descr as "action", 
    role.id as role_id,
    role.descr as role
    FROM 
    public.role_action_def,
    public.role,
    public.record_def, 
    public.action
    WHERE role.id = role_action_def.role_id AND
    record_def.id = role_action_def.def_id AND
    action.id = role_action_def.action_id AND
    role_action_def.account_id = {account_id} AND
    record_def.account_id={account_id} AND
    def_id={def_id}'''
)

Atualização : 29/01/2019 Incorpore a sugestão do @ ShadowRanger de usar em inspect.cleandocvez detextwrap.dedent

Christopher Bruns
fonte
5
Nota: inspect.cleandocé ligeiramente mais agradável do que textwrap.dedent, uma vez que não requer a primeira linha a ser vazio com um carácter de continuação de linha no final.
ShadowRanger 29/01
2
@ShadowRanger Uau, eu nunca usei cleandoc antes. Atualizei minha resposta e, futuramente, utilizarei inspect.cleandocisso.
Christopher Bruns
23

Em Python> = 3.6, você pode usar literais de string formatada (string f)

query= f'''SELECT   action.descr as "action"
    role.id as role_id,
    role.descr as role
    FROM
    public.role_action_def,
    public.role,
    public.record_def,
    public.action
    WHERE role.id = role_action_def.role_id AND
    record_def.id = role_action_def.def_id AND
    action.id = role_action_def.action_id AND
    role_action_def.account_id = {account_id} AND
    record_def.account_id = {account_id} AND
    def_id = {def_id}'''
Vlad Bezden
fonte
4
Como funcionaria uma string f se eu quisesse registrar o resultado de uma string de várias linhas e não exibir as guias / espaços do lado esquerdo?
Kuanb 06/10/19
7
Ainda vulnerável a injeção SQL
Trenton
19

Por exemplo:

sql = ("select field1, field2, field3, field4 "
       "from table "
       "where condition1={} "
       "and condition2={}").format(1, 2)

Output: 'select field1, field2, field3, field4 from table 
         where condition1=1 and condition2=2'

se o valor da condição deve ser uma sequência, você pode fazer o seguinte:

sql = ("select field1, field2, field3, field4 "
       "from table "
       "where condition1='{0}' "
       "and condition2='{1}'").format('2016-10-12', '2017-10-12')

Output: "select field1, field2, field3, field4 from table where
         condition1='2016-10-12' and condition2='2017-10-12'"
pangpang
fonte
13

Acho textwrap.dedento melhor para seqüências longas, como descrito aqui :

def create_snippet():
    code_snippet = textwrap.dedent("""\
        int main(int argc, char* argv[]) {
            return 0;
        }
    """)
    do_something(code_snippet)
fredrik
fonte
1
Gosto da barra preta que impede a nova linha automática, muito obrigado!
ZYY
12

Outros já mencionaram o método entre parênteses, mas eu gostaria de acrescentar que, entre parênteses, comentários embutidos são permitidos.

Comente sobre cada fragmento:

nursery_rhyme = (
    'Mary had a little lamb,'          # Comments are great!
    'its fleece was white as snow.'
    'And everywhere that Mary went,'
    'her sheep would surely go.'       # What a pesky sheep.
)

Comentário não permitido após continuação:

Ao usar continuações de linha de barra invertida ( \), comentários não são permitidos. Você receberá um SyntaxError: unexpected character after line continuation charactererro.

nursery_rhyme = 'Mary had a little lamb,' \  # These comments
    'its fleece was white as snow.'       \  # are invalid!
    'And everywhere that Mary went,'      \
    'her sheep would surely go.'
# => SyntaxError: unexpected character after line continuation character

Melhores comentários para as seqüências de caracteres Regex:

Com base no exemplo de https://docs.python.org/3/library/re.html#re.VERBOSE ,

a = re.compile(
    r'\d+'  # the integral part
    r'\.'   # the decimal point
    r'\d*'  # some fractional digits
)
# Using VERBOSE flag, IDE usually can't syntax highight the string comment.
a = re.compile(r"""\d +  # the integral part
                   \.    # the decimal point
                   \d *  # some fractional digits""", re.X)
ddrscott
fonte
10

Pessoalmente, acho a seguinte a melhor (simples, segura e Pythonic) maneira de escrever consultas SQL brutas em Python, especialmente ao usar o módulo sqlite3 do Python :

query = '''
    SELECT
        action.descr as action,
        role.id as role_id,
        role.descr as role
    FROM
        public.role_action_def,
        public.role,
        public.record_def,
        public.action
    WHERE
        role.id = role_action_def.role_id
        AND record_def.id = role_action_def.def_id
        AND action.id = role_action_def.action_id
        AND role_action_def.account_id = ?
        AND record_def.account_id = ?
        AND def_id = ?
'''
vars = (account_id, account_id, def_id)   # a tuple of query variables
cursor.execute(query, vars)   # using Python's sqlite3 module

Prós

  • Código puro e simples (Pythonic!)
  • Seguro contra injeção de SQL
  • Compatível com o Python 2 e o Python 3 (afinal, é Pythonic)
  • Nenhuma concatenação de string necessária
  • Não é necessário garantir que o caractere mais à direita de cada linha seja um espaço

Contras

  • Como as variáveis ​​na consulta são substituídas pelo ?espaço reservado, pode ser um pouco difícil controlar qual ?deve ser substituído por qual variável Python quando houver muitas na consulta.
Faheel
fonte
Observe que eu não testei isso, mas você provavelmente pode evitar a confusão do ponto de interrogação substituindo-o por "{0} {1} {2}" nos locais relevantes e alterando a última linha para cursor.execute(query.format(vars)). Isso deve cuidar do seu único "engodo" (espero).
Ben
Sim, formatseria bom usar , mas não tenho certeza se a string de consulta formatada dessa maneira estaria protegida contra injeção de SQL.
Faheel
Sim, esse é um argumento justo e certamente pode ser um pouco complicado. Talvez testá-lo em algo totalmente descartável seria sábio ... sem dúvida um comp. Sci. a graduação passará em breve. ;)
Ben
2
@ Bem, se você cursor.execute(query.format(vars))não lucra mais com as instruções preparadas, fica vulnerável a muitos tipos de problemas, começando com o fato de que, se os parâmetros não forem apenas números, você precisará citá-los duas vezes na consulta SQL.
Patrick Mevzek
4

Eu costumo usar algo como isto:

text = '''
    This string was typed to be a demo
    on how could we write a multi-line
    text in Python.
'''

Se você deseja remover espaços em branco irritantes em cada linha, faça o seguinte:

text = '\n'.join(line.lstrip() for line in text.splitlines())
Israel Barth Rubio
fonte
2
Veja a textwrap.dedentfunção do Python , que está na biblioteca padrão, e tem a funcionalidade que você precisa.
precisa saber é o seguinte
@ bjd2385: inspect.cleandocé um pouco melhor (menos meticuloso sobre se o texto aparece ou não na mesma linha que as aspas abertas, não requer caracteres explícitos de continuação de linha).
ShadowRanger
3

Seu código real não deve funcionar, faltam espaços em branco no final de "linhas" (por exemplo role.descr as roleFROM...:)

Há citações triplas para sequência de várias linhas:

string = """line
  line2
  line3"""

Ele conterá as quebras de linha e espaços extras, mas para SQL isso não é um problema.

Karoly Horvath
fonte
3

Você também pode colocar a instrução sql em um arquivo separado action.sqle carregá-la no arquivo py com

with open('action.sql') as f:
   query = f.read()

Portanto, as instruções sql serão separadas do código python. Se houver parâmetros na instrução sql que precisem ser preenchidos com python, você poderá usar a formatação de strings (como% s ou {field})

Mrijken
fonte
3

Maneira "à la" Scala (mas acho que é a maneira mais pitônica que o OQ exige):

description = """
            | The intention of this module is to provide a method to 
            | pass meta information in markdown_ header files for 
            | using it in jinja_ templates. 
            | 
            | Also, to provide a method to use markdown files as jinja 
            | templates. Maybe you prefer to see the code than 
            | to install it.""".replace('\n            | \n','\n').replace('            | ',' ')

Se você deseja str final sem linhas de salto, basta colocar \nno início do primeiro argumento do segundo substituir:

.replace('\n            | ',' ')`.

Nota: a linha branca entre "... modelos". e "Além disso, ..." requer um espaço em branco após o |.

victe
fonte
3

tl; dr: use """\e """para quebrar a sequência , como em

string = """\
This is a long string
spanning multiple lines.
"""

Na documentação oficial do python :

Literais de string podem abranger várias linhas. Uma maneira é usar aspas triplas: "" "..." "" ou '' '...' ''. O fim das linhas é incluído automaticamente na string, mas é possível evitar isso adicionando um \ no final da linha. O exemplo a seguir:

print("""\
Usage: thingy [OPTIONS]
     -h                        Display this usage message
     -H hostname               Hostname to connect to
""")

produz a seguinte saída (observe que a nova linha inicial não está incluída):

Usage: thingy [OPTIONS]
     -h                        Display this usage message
     -H hostname               Hostname to connect to
Fluxo
fonte
2

Ei, tente algo como esta esperança que funcione, como neste formato, você retornará uma linha contínua, como você perguntou com sucesso sobre essa propriedade`

"message": f'you have successfully inquired about '
           f'{enquiring_property.title} Property owned by '
           f'{enquiring_property.client}'
Kelvin Onkundi
fonte
1

Eu uso uma função recursiva para criar consultas SQL complexas. Essa técnica geralmente pode ser usada para criar cadeias grandes, mantendo a legibilidade do código.

# Utility function to recursively resolve SQL statements.
# CAUTION: Use this function carefully, Pass correct SQL parameters {},
# TODO: This should never happen but check for infinite loops
def resolveSQL(sql_seed, sqlparams):
    sql = sql_seed % (sqlparams)
    if sql == sql_seed:
        return ' '.join([x.strip() for x in sql.split()])
    else:
        return resolveSQL(sql, sqlparams)

PS: Dê uma olhada na incrível biblioteca python-sqlparse para imprimir consultas SQL, se necessário. http://sqlparse.readthedocs.org/en/latest/api/#sqlparse.format

Sandeep
fonte
"função recursiva" não é chamada lambda?
M3nda
1

Outra opção que eu acho que é mais legível quando o código (por exemplo, variável) é recuado e a string de saída deve ser um liner (sem novas linhas):

def some_method():

    long_string = """
a presumptuous long string 
which looks a bit nicer 
in a text editor when
written over multiple lines
""".strip('\n').replace('\n', ' ')

    return long_string 
Eyal Levin
fonte
1

Use aspas triplas. As pessoas costumam usá-las para criar documentos no início dos programas para explicar seus propósitos e outras informações relevantes para sua criação. As pessoas também as usam em funções para explicar o objetivo e a aplicação das funções. Exemplo:

'''
Filename: practice.py
File creator: me
File purpose: explain triple quotes
'''


def example():
    """This prints a string that occupies multiple lines!!"""
    print("""
    This
    is 
    a multi-line
    string!
    """)
Joshua Hall
fonte
0

Eu gosto dessa abordagem porque privilegia a leitura. Nos casos em que temos longas cordas, não há como! Dependendo do nível de indentação em que você se encontra e ainda limitado a 80 caracteres por linha ... Bem ... Não há necessidade de dizer mais nada. Na minha opinião, os guias de estilo python ainda são muito vagos. Adotei a abordagem @Eero Aaltonen, porque privilegia a leitura e o bom senso. Entendo que os guias de estilo devem nos ajudar e não tornar nossa vida uma bagunça. Obrigado!

class ClassName():
    def method_name():
        if condition_0:
            if condition_1:
                if condition_2:
                    some_variable_0 =\
"""
some_js_func_call(
    undefined, 
    {
        'some_attr_0': 'value_0', 
        'some_attr_1': 'value_1', 
        'some_attr_2': '""" + some_variable_1 + """'
    }, 
    undefined, 
    undefined, 
    true
)
"""
Eduardo Lucio
fonte
0

Na documentação oficial do python :

Literais de string podem abranger várias linhas. Uma maneira é usar aspas triplas: "" "..." "" ou '' '...' ''. O fim das linhas é incluído automaticamente na string, mas é possível evitar isso adicionando um \ no final da linha. O exemplo a seguir:

print("""\
Usage: thingy [OPTIONS]
     -h                        Display this usage message
     -H hostname               Hostname to connect to
""")

produz a seguinte saída (observe que a nova linha inicial não está incluída):

Fluxo
fonte
0

Para definir uma string longa dentro de um dict, mantendo as novas linhas, mas omitindo os espaços , acabei definindo a string em uma constante assim:

LONG_STRING = \
"""
This is a long sting
that contains newlines.
The newlines are important.
"""

my_dict = {
   'foo': 'bar',
   'string': LONG_STRING
}
flix
fonte
0

Como uma abordagem geral para seqüências longas em Python, você pode usar aspas triplas splite join:

_str = ' '.join('''Lorem ipsum dolor sit amet, consectetur adipiscing 
        elit, sed do eiusmod tempor incididunt ut labore et dolore 
        magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation 
        ullamco laboris nisi ut aliquip ex ea commodo.'''.split())

Resultado:

'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo.'

Com relação à pergunta do OP relacionada a uma consulta SQL, a resposta abaixo desconsidera a correção dessa abordagem na criação de consultas SQL e se concentra apenas na criação de cadeias longas de maneira legível e estética, sem importações adicionais. Também desconsidera a carga computacional que isso implica.

Usando aspas triplas, construímos uma string longa e legível, que depois dividimos em uma lista split(), eliminando o espaço em branco e juntando-a novamente ' '.join(). Finalmente, inserimos as variáveis ​​usando o format()comando:

account_id = 123
def_id = 321

_str = '''
    SELECT action.descr AS "action", role.id AS role_id, role.descr AS role 
    FROM public.role_action_def, public.role, public.record_def, public.action
    WHERE role.id = role_action_def.role_id 
    AND record_def.id = role_action_def.def_id 
    AND' action.id = role_action_def.action_id 
    AND role_action_def.account_id = {} 
    AND record_def.account_id = {} 
    AND def_id = {}
    '''

query = ' '.join(_str.split()).format(account_id, account_id, def_id)

Produz:

SELECT action.descr AS "action", role.id AS role_id, role.descr AS role FROM public.role_action_def, public.role, public.record_def, public.action WHERE role.id = role_action_def.role_id AND record_def.id = role_action_def.def_id AND\' action.id = role_action_def.action_id AND role_action_def.account_id = 123 AND record_def.account_id=123 AND def_id=321

Edit: Esta abordagem não está de acordo com o PEP8, mas acho útil às vezes

Rasmus Groth
fonte
-7

Geralmente, eu uso liste joinpara comentários / linhas com várias linhas.

lines = list()
lines.append('SELECT action.enter code here descr as "action", ')
lines.append('role.id as role_id,')
lines.append('role.descr as role')
lines.append('FROM ')
lines.append('public.role_action_def,')
lines.append('public.role,')
lines.append('public.record_def, ')
lines.append('public.action')
query = " ".join(lines)

você pode usar qualquer sequência para juntar todo esse elemento da lista como ' \n' (nova linha) ou ' ,' (vírgula) ou ' ' (espaço)

Felicidades..!!

paone
fonte
1
Por que você não usaria pelo menos uma matriz literal?
Alexander - Restabelece Monica
1
Matrizes são representadas pela lista de classes. confira outra discussão sobre os literais do array
paone 12/11/18
Suponho que isso funciona, mas você deve pensar sobre o desempenho e legibilidade ...
Petro