Manière pythonique de créer une longue chaîne multi-ligne

1307

J'ai une très longue requête. Je voudrais le diviser en plusieurs lignes en Python. Une façon de le faire en JavaScript serait d'utiliser plusieurs phrases et de les joindre à un +opérateur (je sais, ce n'est peut-être pas le moyen le plus efficace de le faire, mais je ne suis pas vraiment préoccupé par les performances à ce stade, juste la lisibilité du code) . Exemple:

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

J'ai essayé de faire quelque chose de similaire en Python, mais cela n'a pas fonctionné, j'ai donc l'habitude \de diviser la longue chaîne. Cependant, je ne suis pas sûr que ce soit la seule / meilleure / meilleure façon de le faire. Ça a l'air maladroit. Code réel:

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
la source
208
Étant donné que votre exemple ressemble à un bloc SQL en attente d'une attaque par injection, une autre suggestion consiste à examiner une bibliothèque SQL de niveau supérieur comme SQLAlchemy ou quelque chose pour éviter de pirater ensemble du SQL brut comme celui-ci. (Peut-être hors sujet, mais vous avez demandé "Toutes suggestions".;)
John Gaines Jr.
6
Il s'agit de la "méthode Pythonic pour créer du code multiligne pour une chaîne longue". Pour créer une chaîne contenant des sauts de ligne, voir textwrap.dedent .
Bob Stein
8
@cezar J'ai écrit cette question il y a plus de cinq ans, mais je me souviens qu'elle est née du fait de ne pas savoir comment placer correctement la requête SQL longue en plusieurs lignes. Je suis d'accord que je faisais des choses stupides avec cette longue chaîne, mais ce n'était pas ma question et je n'étais pas assez intelligent pour chercher un meilleur exemple pour l'illustrer qui n'incluait pas quelques problèmes d'injection SQL.
Pablo Mescher
@cezar non, ce n'est pas un problème XY, la requête serait dans tous les cas mieux formatée sur plusieurs lignes. SQLi n'est pas lié à la question à l'étude. Les gros avertissements audacieux sont cependant totalement justifiés :)
bugmenot123
J'ai écrit un petit paquet pour ça. Exemple ici: stackoverflow.com/a/56940938/1842491
Shay

Réponses:

2229

Parlez-vous de chaînes multi-lignes? Facile, utilisez des guillemets triples pour les démarrer et les terminer.

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

Vous pouvez également utiliser des guillemets simples (3 d'entre eux bien sûr au début et à la fin) et traiter la chaîne résultante scomme n'importe quelle autre chaîne.

REMARQUE : comme pour toute chaîne, tout ce qui se trouve entre les guillemets de début et de fin fait partie de la chaîne, donc cet exemple a un blanc de début (comme indiqué par @ root45). Cette chaîne contiendra également des espaces et des sauts de ligne.

C'est à dire,:

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

Enfin, on peut également construire de longues lignes en Python comme ceci:

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

qui ne comprend aucun espace supplémentaire ou (ce qui est des sauts de ligne un exemple montrant délibérément ce que l'effet de sauter des blancs entraînera):

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

Aucune virgule n'est requise, placez simplement les chaînes à assembler dans une paire de parenthèses et assurez-vous de prendre en compte les blancs et les nouvelles lignes nécessaires.

Levon
la source
8
Je préfère utiliser explicitement l'opérateur "+" pour la deuxième méthode. Pas beaucoup de tracas et améliore la lisibilité.
Marco Sulla
38
@LucasMalor Les chaînes adjacentes sont une concaténation au moment de la compilation. L'utilisation de l' +opérateur ne fait-elle pas la concaténation au moment de l'exécution?
Joshua Taylor
13
Pour référence, voici les documents officiels de ce phénomène: docs.python.org/2/reference/… (python 2) et docs.python.org/3/reference/… (python 3)
neverendingqs
4
Votre exemple est bon, mais j'aurais aimé qu'il comprenne comment intégrer de manière sûre et sécurisée des données variables dans la requête. L'exemple de code OP et @jessee montre comment NE PAS le faire correctement (ce sont des invitations à des attaques SQL). Voir aussi: dev.mysql.com/doc/connector-python/en/…
Scott Prive
2
vous pouvez utiliser textwrap.dedentpour supprimer les espaces blancs non désirés. docs.python.org/3/library/textwrap.html#textwrap.dedent
Corey Goldberg
190

Si vous ne voulez pas de chaîne multiligne mais que vous n'avez qu'une longue chaîne à une seule ligne, vous pouvez utiliser des parenthèses, assurez-vous simplement de ne pas inclure de virgules entre les segments de chaîne, ce sera un tuple.

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)

Dans une instruction SQL comme celle que vous construisez, les chaînes multilignes conviendraient également. Mais si l'espace blanc supplémentaire qu'une chaîne multiligne contiendrait serait un problème, alors ce serait un bon moyen de réaliser ce que vous voulez.

Jesse
la source
1
@Pablo, vous pouvez même ajouter des commentaires après le,
Ashwini Chaudhary
@ 200OK tu veux dire après '?
kon psych
3
Une autre façon de formater cette chaîne serait d'ajouter .format(...)après la parenthèse fermante. %le formatage de la notation doit aussi fonctionner mais je ne l'ai pas essayé
kon psych
3
Notez que chaque ligne doit se terminer par une constante de chaîne, donc ' foo '+variablene fonctionnera pas, mais le ' foo '+variable+''fera.
yoyo
46
Cet exemple est une porte ouverte aux attaques par injection SQL. S'il vous plaît, personne ne l'utilise sur aucune application destinée au public. Consultez les documents MySQL pour savoir comment utiliser les 'espaces réservés': dev.mysql.com/doc/connector-python/en/…
Scott Prive
138

Briser les lignes par les \œuvres pour moi. Voici un exemple:

longStr = "This is a very long string " \
        "that I wrote to help somebody " \
        "who had a question about " \
        "writing long strings in Python"
amphibient
la source
9
Je préférerais soit la notation à trois guillemets, soit l'habillage à l'intérieur () au caractère \
Khanh Hua
15
Je conseille fortement de mettre les espaces au début des lignes suivantes plutôt qu'à la fin des lignes suivies. De cette façon, un manquant accidentellement est beaucoup plus évident (et est donc moins susceptible de se produire).
Alfe
longStr = "account: " + account_id + \ ...
Fonctionne
Je reçois l' erreur suivante: the backslash is redundant between bracketsquand je l' ai écrit à l' intérieurprint()
Alper
50

Je me suis contenté de celui-ci:

string = """This is a
very long string,
containing commas,
that I split up
for readability""".replace('\n',' ')
Eero Aaltonen
la source
32
Être en désaccord. Que faire si la première ligne ("string = ...") est fortement en retrait? Il faudrait détacher les lignes suivantes à une indentation nulle, ce qui semble laid au milieu d'un bloc autrement indenté.
xjcl
1
Eh bien, la majorité de mes longues chaînes se produisent au niveau du module, où cela correspond bien. Dans votre cas, ce ne serait évidemment pas la meilleure solution.
Eero Aaltonen
1
J'aime cette approche car elle privilégie la lecture. Dans les cas où nous avons de longues chaînes, il n'y a aucun moyen ... Selon le niveau d'indentation dans lequel vous vous trouvez et toujours limité à 80 caractères par ligne ... Eh bien ... Pas besoin de dire autre chose. À mon avis, les guides de style python sont encore très vagues. Merci!
Eduardo Lucio
Ce serait si moche s'il est utilisé sous un module, je dois aussi.replace('\t','')
alper
44

Je trouve que lors de la construction de longues chaînes, vous faites généralement quelque chose comme la construction d'une requête SQL, auquel cas c'est le meilleur:

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

Ce que Levon a suggéré est bon, mais pourrait être vulnérable aux erreurs:

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

query == "SELECT fooFROM barWHERE baz"  # probably not what you want
darkfeline
la source
8
+1 Soulage le réviseur de code d'avoir à vérifier assidûment l'extrémité droite de chaque ligne pour un espace insuffisant . Le PO a commis cette erreur à plusieurs reprises, comme l'a noté @KarolyHorvath.
Bob Stein
2
Lors de l'examen de chaînes multilignes codées de la même manière, j'ai besoin d'un espace suffisant à l' extrémité gauche de chaque ligne pour une confirmation facile.
Umbrella
3
@ Les révisions du code BobStein-VisiBone ne devraient pas porter sur des erreurs de syntaxe ou de petits bugs comme celui-ci, elles devraient porter sur le fond. Si quelqu'un met du code à l'examen qui contient des erreurs de syntaxe (et ne s'exécute donc pas du tout ou dans certaines situations), quelque chose ne va vraiment pas. Il n'est pas difficile d'exécuter des peluches avant de vous engager. Si la personne n'a pas remarqué que son programme ne fonctionne pas correctement parce qu'elle a fait une erreur si évidente, elle ne devrait pas s'engager.
Charles Addis
1
D'accord @CharlesAddis, les revues de code devraient venir après des méthodes automatisées, par exemple lint, la coloration syntaxique, etc. Cependant, certains bogues manquant d'espace blanc peuvent ne pas être détectés de cette façon. Bénéficiez de tous les avantages raisonnables de la protection contre les bugs, je suggère.
Bob Stein
33

Vous pouvez également concaténer des variables lorsque vous utilisez la notation "" ":

foo = '1234'

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

EDIT: Trouvé une meilleure façon, avec des paramètres nommés et .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
la source
26

Cette approche utilise:

  • une seule barre oblique inverse pour éviter un saut de ligne initial
  • presque aucune ponctuation interne en utilisant une chaîne entre guillemets triples
  • supprime l'indentation locale à l'aide du module textwrap inspect
  • utilise l'interpolation de chaîne au format python 3.6 ('f') pour les variables account_idet def_id.

De cette façon, cela me semble le plus pythonique.

# 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}'''
)

Mise à jour : 29/01/2019 Incorporez la suggestion de @ ShadowRanger à utiliser inspect.cleandocau lieu detextwrap.dedent

Christopher Bruns
la source
5
Remarque: inspect.cleandocest légèrement plus agréable que textwrap.dedent, car il ne nécessite pas que la première ligne soit vide avec un caractère de continuation de ligne à la fin.
ShadowRanger
2
@ShadowRanger Wow, je n'avais jamais utilisé cleandoc auparavant. J'ai mis à jour ma réponse et je l'utiliserai à l'avenir inspect.cleandocpour cela.
Christopher Bruns
23

En Python> = 3.6, vous pouvez utiliser des littéraux de chaîne formatés (chaîne 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
la source
4
Comment une chaîne f fonctionnerait-elle si je voulais enregistrer le résultat d'une chaîne multi-lignes et que les onglets / espaces de gauche ne soient pas affichés?
kuanb
7
Toujours vulnérable à l'injection SQL
Trenton
19

Par exemple:

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'

si la valeur de condition doit être une chaîne, vous pouvez faire comme ceci:

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
la source
13

Je trouve textwrap.dedentle meilleur pour les cordes longues comme décrit ici :

def create_snippet():
    code_snippet = textwrap.dedent("""\
        int main(int argc, char* argv[]) {
            return 0;
        }
    """)
    do_something(code_snippet)
Fredrik
la source
1
J'aime la barre noire qui empêche la nouvelle ligne automatique, merci beaucoup!
zyy
12

D'autres ont déjà mentionné la méthode des parenthèses, mais j'aimerais ajouter qu'avec les parenthèses, les commentaires en ligne sont autorisés.

Commentez chaque fragment:

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

Commentaire non autorisé après la suite:

Lors de l'utilisation de continuations de ligne de barre oblique inverse ( \), les commentaires ne sont pas autorisés. Vous recevrez une SyntaxError: unexpected character after line continuation charactererreur.

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

Meilleurs commentaires pour les chaînes Regex:

Basé sur l'exemple 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
la source
10

Personnellement, je trouve que ce qui suit est le meilleur moyen (simple, sûr et Pythonic) d'écrire des requêtes SQL brutes en Python, en particulier lors de l'utilisation du module sqlite3 de 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

Avantages

  • Code soigné et simple (Pythonic!)
  • À l'abri de l'injection SQL
  • Compatible avec Python 2 et Python 3 (c'est Pythonic après tout)
  • Aucune concaténation de chaîne requise
  • Pas besoin de s'assurer que le caractère le plus à droite de chaque ligne est un espace

Les inconvénients

  • Étant donné que les variables de la requête sont remplacées par l' ?espace réservé, il peut devenir un peu difficile de savoir laquelle ?doit être remplacée par quelle variable Python lorsqu'il y en a beaucoup dans la requête.
Faheel
la source
Remarque, je n'ai pas testé cela, mais vous pouvez probablement éviter la confusion du point d'interrogation en les remplaçant par "{0} {1} {2}" aux endroits appropriés, puis en remplaçant la dernière ligne par cursor.execute(query.format(vars)). Cela devrait prendre soin de votre seul "con" (j'espère).
Ben
Oui, utiliser formatserait bien, mais je ne suis pas sûr que la chaîne de requête formatée de cette façon soit à l'abri de l'injection SQL.
Faheel
Oui, c'est un bon point et cela pourrait certainement devenir un peu délicat. Peut-être que le tester sur quelque chose de totalement consommable serait sage ... sans aucun doute un Comp. Sci. le premier cycle passera assez tôt. ;)
Ben
2
@Ben si vous ne cursor.execute(query.format(vars))bénéficiez plus des instructions préparées, vous êtes donc vulnérable à de nombreux types de problèmes, à commencer par le fait que si les paramètres ne sont pas uniquement des nombres, vous devez les citer deux fois dans la requête SQL.
Patrick Mevzek
4

J'utilise habituellement quelque chose comme ça:

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

Si vous souhaitez supprimer les espaces vides ennuyeux dans chaque ligne, vous pouvez procéder comme suit:

text = '\n'.join(line.lstrip() for line in text.splitlines())
Israël Barth Rubio
la source
2
Regardez dans la textwrap.dedentfonction de Python , qui se trouve dans la bibliothèque standard, elle a les fonctionnalités dont vous avez besoin.
bjd2385
@ bjd2385: inspect.cleandocest légèrement plus agréable (moins capricieux quant à savoir si le texte apparaît ou non sur la même ligne que les guillemets ouverts, ne nécessite pas de caractères de continuation de ligne explicites).
ShadowRanger
3

Votre code actuel ne doit pas travailler, il vous manque espaces à l'extrémité des « lignes » (par exemple: role.descr as roleFROM...)

Il existe des guillemets triples pour la chaîne multiligne:

string = """line
  line2
  line3"""

Il contiendra les sauts de ligne et les espaces supplémentaires, mais pour SQL ce n'est pas un problème.

Karoly Horvath
la source
3

Vous pouvez également placer l'instruction sql dans un fichier séparé action.sqlet la charger dans le fichier py avec

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

Ainsi, les instructions sql seront séparées du code python. S'il y a des paramètres dans l'instruction sql qui doivent être remplis à partir de python, vous pouvez utiliser le formatage de chaînes (comme% s ou {field})

mrijken
la source
3

"À la" façon Scala (mais je pense que c'est la façon la plus pythonique comme OQ l'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('            | ',' ')

Si vous voulez une chaîne finale sans lignes de saut, mettez simplement \nau début du premier argument du deuxième remplacement:

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

Remarque: la ligne blanche entre "... modèles". et "Aussi, ..." nécessite un espace après le |.

victe
la source
3

tl; dr: utilisez """\et """pour envelopper la chaîne , comme dans

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

De la documentation officielle de python :

Les littéraux de chaîne peuvent s'étendre sur plusieurs lignes. Une façon consiste à utiliser des guillemets triples: "" "..." "" ou '' '...' ''. La fin des lignes est automatiquement incluse dans la chaîne, mais il est possible d'empêcher cela en ajoutant un \ à la fin de la ligne. L'exemple suivant:

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

produit la sortie suivante (notez que la nouvelle ligne initiale n'est pas incluse):

Usage: thingy [OPTIONS]
     -h                        Display this usage message
     -H hostname               Hostname to connect to
Couler
la source
2

Hé, essayez quelque chose comme ça, j'espère que cela fonctionne, comme dans ce format, il vous renverra une ligne continue comme si vous vous êtes bien renseigné sur cette propriété.

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

J'utilise une fonction récursive pour construire des requêtes SQL complexes. Cette technique peut généralement être utilisée pour créer de grandes chaînes tout en conservant la lisibilité du code.

# 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: Jetez un oeil à la bibliothèque impressionnante python-sqlparse pour joliment imprimer des requêtes SQL si nécessaire. http://sqlparse.readthedocs.org/en/latest/api/#sqlparse.format

Sandeep
la source
"fonction récursive" n'est-ce pas ce qu'on appelle lambda?
m3nda
1

Une autre option qui, à mon avis, est plus lisible lorsque le code (par exemple, une variable) est en retrait et que la chaîne de sortie doit être une ligne (pas de nouvelle ligne):

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
la source
1

Utilisez des guillemets triples. Les gens les utilisent souvent pour créer des docstrings au début des programmes pour expliquer leur objectif et d'autres informations pertinentes à sa création. Les gens les utilisent également dans les fonctions pour expliquer le but et l'application des fonctions. Exemple:

'''
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
la source
0

J'aime cette approche car elle privilégie la lecture. Dans les cas où nous avons de longues cordes, il n'y a aucun moyen! Selon le niveau d'indentation dans lequel vous vous trouvez et toujours limité à 80 caractères par ligne ... Et bien ... Pas besoin de dire autre chose. À mon avis, les guides de style python sont encore très vagues. J'ai adopté l'approche @Eero Aaltonen car elle privilégie la lecture et le bon sens. Je comprends que les guides de style devraient nous aider et ne pas gâcher notre vie. Merci!

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
la source
0

De la documentation officielle de python :

Les littéraux de chaîne peuvent s'étendre sur plusieurs lignes. Une façon consiste à utiliser des guillemets triples: "" "..." "" ou '' '...' ''. La fin des lignes est automatiquement incluse dans la chaîne, mais il est possible d'empêcher cela en ajoutant un \ à la fin de la ligne. L'exemple suivant:

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

produit la sortie suivante (notez que la nouvelle ligne initiale n'est pas incluse):

Couler
la source
0

Pour définir une longue chaîne à l'intérieur d'un dict, en gardant les sauts de ligne mais en omettant les espaces , j'ai fini par définir la chaîne dans une constante comme celle-ci:

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

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

En tant qu'approche générale des chaînes longues en Python, vous pouvez utiliser des guillemets triples splitet 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())

Production:

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

En ce qui concerne la question d'OP relative à une requête SQL, la réponse ci-dessous ne tient pas compte de l'exactitude de cette approche de construction de requêtes SQL et se concentre uniquement sur la construction de longues chaînes de manière lisible et esthétique sans importations supplémentaires. Il ignore également la charge de calcul que cela implique.

En utilisant des guillemets triples, nous construisons une chaîne longue et lisible que nous décomposons ensuite en une liste en utilisant split()ainsi en supprimant les espaces blancs, puis en les réunissant à nouveau avec ' '.join(). Enfin, nous insérons les variables à l'aide de la format()commande:

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)

Produit:

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: Cette approche n'est pas conforme à PEP8 mais je la trouve parfois utile

Rasmus Groth
la source
-7

En général, j'utilise listet joinpour les commentaires / chaîne multi-lignes.

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)

vous pouvez utiliser n'importe quelle chaîne pour joindre tous ces éléments de la liste comme ' \n' (nouvelle ligne) ou ' ,' (virgule) ou ' ' (espace)

À votre santé..!!

paone
la source
1
Pourquoi n'utilisez-vous pas au moins un littéral de tableau?
Alexander - Rétablir Monica
1
Les tableaux sont représentés par une liste de classes. consultez une autre discussion concernant les littéraux de tableau
paone
Je suppose que cela fonctionne, mais vous devriez penser aux performances et à la lisibilité ...
Petro