Question

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 consisterait à utiliser plusieurs phrases et à les joindre par 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 par 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é, alors j'ai utilisé \ pour diviser la longue chaîne.Cependant, je ne suis pas sûr que ce soit la seule/la meilleure/la manière la plus pythonique de le faire.Cela semble gênant.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
Était-ce utile?

La solution

Parlez-vous de chaînes multilignes ?Facile, utilisez des guillemets triples pour les commencer 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 s comme n'importe quelle autre chaîne.

NOTE:Comme pour n'importe quelle chaîne, tout ce qui se trouve entre les guillemets de début et de fin devient une partie de la chaîne, donc cet exemple comporte un espace de début (comme l'a souligné @root45).Cette chaîne contiendra également des espaces et des nouvelles lignes.

C'est à dire.,:

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

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

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

Qui va pas incluez tous les espaces ou nouvelles lignes supplémentaires (il s'agit d'un exemple délibéré montrant l'effet du saut des espaces):

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

Aucune virgule n'est requise, placez simplement les chaînes à joindre dans une paire de parenthèses et assurez-vous de tenir compte des espaces et des nouvelles lignes nécessaires.

Autres conseils

Si vous ne voulez pas de chaîne multiligne mais simplement une longue chaîne sur 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 alors 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 supplémentaire qu’une chaîne multiligne contiendrait serait un problème, alors ce serait un bon moyen d’obtenir ce que vous voulez.

Rompre les lignes par \ travaille 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"

Je me suis retrouvé content de celui-ci :

string = """This is a
very long string,
containing commas,
that I split up
for readability""".replace('\n',' ')

Je trouve que lorsque vous créez de longues chaînes, vous faites généralement quelque chose comme créer une requête SQL, auquel cas c'est mieux :

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 sujet à des erreurs :

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

query == "SELECT fooFROM barWHERE baz"  # probably not what you want

Vous pouvez également concaténer des variables en utilisant la notation "" :

foo = '1234'

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

MODIFIER:J'ai trouvé une meilleure façon, avec les 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)

Cette approche utilise :

  • juste une barre oblique inverse pour éviter un saut de ligne initial
  • presque pas de ponctuation interne en utilisant une chaîne entre guillemets triples
  • supprime l'indentation locale à l'aide de la habillage de texte inspect module
  • utilise l'interpolation de chaîne au format Python 3.6 (« f ») pour le account_id et def_id variables.

Cette méthode me semble la 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 Incorporer la suggestion d'utilisation de @ShadowRanger inspect.cleandoc au lieu de textwrap.dedent

En Python >= 3.6, vous pouvez utiliser 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}'''

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 la condition doit être une chaîne, vous pouvez procéder 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'"

Personnellement, je trouve que ce qui suit est le meilleur moyen (simple, sûr et pythonique) d'écrire des requêtes SQL brutes en Python, en particulier lors de l'utilisation de Le 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 des injections SQL
  • Compatible avec Python 2 et Python 3 (c'est Pythonic après tout)
  • Aucune concaténation de chaînes requise
  • Pas besoin de s'assurer que le caractère le plus à droite de chaque ligne est un espace

Les inconvénients

  • Puisque les variables de la requête sont remplacées par le ? espace réservé, il peut devenir un peu difficile de savoir lequel ? doit être remplacé par which variable Python lorsqu'il y en a beaucoup dans la requête.

je trouve textwrap.dedent le meilleur pour les longues cordes comme décrit ici:

def create_snippet():
    code_snippet = textwrap.dedent("""\
        int main(int argc, char* argv[]) {
            return 0;
        }
    """)
    do_something(code_snippet)

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 un SyntaxError: unexpected character after line continuation character erreur.

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)

J'utilise habituellement quelque chose comme ceci :

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 gênants dans chaque ligne, vous pouvez procéder comme suit :

text = '\n'.join(line.lstrip() for line in text.splitlines())

Votre code actuel ne devrait pas fonctionner, il vous manque des espaces à la fin des "lignes" (par exemple : role.descr as roleFROM...)

Il existe des guillemets triples pour une 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.

Vous pouvez également placer l'instruction SQL dans un fichier séparé action.sql et chargez-le 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îne (comme %s ou {field})

"À la" Échelle manière (mais je pense que c'est la manière la plus pythonique comme l'exige OQ) :

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 \n au début du premier argument du deuxième remplacement :

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

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

tl;dr :Utiliser """\ et """ enrouler la ficelle, un péché

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

Du documentation officielle de Python:

Les littéraux de chaîne peuvent s'étendre sur plusieurs lignes.Une façon consiste à utiliser des triple-quotes:"""...""" 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

J'utilise une fonction récursive pour créer des requêtes SQL complexes.Cette technique peut généralement être utilisée pour créer des chaînes volumineuses 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)

P.S :Jetez un œil à l'impressionnante bibliothèque python-sqlparse pour imprimer joliment les requêtes SQL si nécessaire.http://sqlparse.readthedocs.org/en/latest/api/#sqlparse.format

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 seule 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 

Hé, essayez quelque chose comme ceci, j'espère que cela fonctionnera, comme dans ce format, cela vous renverra une ligne continue comme si vous aviez réussi à vous renseigner sur cette propriété.

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

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...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 nos vies.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
)
"""

Du documentation officielle de Python:

Les littéraux de chaîne peuvent s'étendre sur plusieurs lignes.Une façon consiste à utiliser des triple-quotes:"""...""" 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):

En général, j'utilise list et join pour les commentaires/chaînes multilignes.

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 liste comme '\n'(nouvelle ligne) ou ','(virgule) ou ''(espace)

Acclamations..!!

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top