Vraag Opmaak zonder tekenreeks in python2.6


Ik heb vele duizenden regels python-code met stringopmaak in python2.7 + -stijl (bijvoorbeeld zonder indexen in de {} s)

"{} {}".format('foo', 'bar')

Ik moet deze code uitvoeren onder python2.6 en python2.6 vereist de indices.

Ik vraag me af of iemand die weet van een pijnloze manier Python2.6 toestaat deze code uit te voeren. Het zou geweldig zijn als er een "from __future__ import blah" -oplossing voor het probleem was. Ik zie er geen. Iets in die zin zou mijn eerste keuze zijn.

Een verre seconde zou een script zijn dat het proces van het toevoegen van de indexen kan automatiseren, althans in de voor de hand liggende gevallen:

"{0} {1}".format('foo', 'bar')

13
2017-12-11 16:08


oorsprong


antwoorden:


Het behoudt niet echt de witruimte en zou waarschijnlijk een beetje slimmer gemaakt kunnen worden, maar het zal op zijn minst Python-strings (apostrophes / quotes / multi line) correct identificeren zonder gebruik te maken van een regex of externe parser:

import tokenize
from itertools import count
import re

with open('your_file') as fin:
    output = []
    tokens = tokenize.generate_tokens(fin.readline)
    for num, val in (token[:2] for token in tokens):
        if num == tokenize.STRING:
            val = re.sub('{}', lambda L, c=count(): '{{{0}}}'.format(next(c)), val)
        output.append((num, val))

print tokenize.untokenize(output) # write to file instead...

Voorbeeld invoer:

s = "{} {}".format('foo', 'bar')
if something:
    do_something('{} {} {}'.format(1, 2, 3))

Voorbeelduitvoer (noteer een beetje dubieus witruimte-effect):

s ="{0} {1}".format ('foo','bar')
if something :
    do_something ('{0} {1} {2}'.format (1 ,2 ,3 ))

6
2017-12-11 17:18



U zou een functie kunnen definiëren om uw formatstrings opnieuw in te delen:

def reformat(s):
    return "".join("".join((x, str(i), "}")) 
                   for i, x in list(enumerate(s.split("}")))[:-1])

0
2017-12-11 16:25



Misschien een goede oude sed-regex zoals:

sed source.py -e 's/{}/%s/g; s/\.format(/ % (/'

je voorbeeld zou veranderen in iets als:

"%s %s" % ('foo', 'bar')

Je hebt de mooie nieuwe stijl verloren .format() maar het is bijna nooit nuttig voor triviale waarde-invoegingen.


0
2017-12-11 16:54



Een conversiescript kan vrij eenvoudig zijn. Je kunt strings vinden om te vervangen door regex:

fmt = "['\"][^'\"]*{}.*?['\"]\.format"

str1 = "x; '{} {}'.format(['foo', 'bar'])"
str2 = "This is a function; 'First is {}, second is {}'.format(['x1', 'x2']); some more code"
str3 = 'This doesn't have anything but a format. format(x)'
str4 = "This has an old-style format; '{0} {1}'.format(['some', 'list'])"
str5 = "'{0}'.format(1); '{} {}'.format(['x', 'y'])"

def add_format_indices(instr):
    text = instr.group(0)
    i = 0
    while '{}' in text:
        text = text.replace('{}', '{%d}'%i, 1)
        i = i+1
    return text

def reformat_text(text):
    return re.sub(fmt, add_format_indices, text)

reformat_text(str1)
"x; '{0} {1}'.format(['foo', 'bar'])"
reformat_text(str2)
"This is a function; 'First is {0}, second is {1}'.format(['x1', 'x2']); some more code"
reformat_text(str3)
"This doesn't have anything but a format. format(x)"
reformat_text(str4)
"This has an old-style format; '{0} {1}'.format(['some', 'list'])"
reformat_text(str5)
"'{0}'.format(1); '{0} {1}'.format(['x', 'y'])"

Ik denk dat je hier een heel dossier doorheen kunt gooien. Je kunt waarschijnlijk een snellere implementatie van add_format_indices vinden, en het is duidelijk dat het niet veel is getest.

Jammer dat er geen is import __past__, maar in het algemeen is dat niet iets dat gewoonlijk wordt aangeboden (zie het 2to3-script voor een voorbeeld), dus dit is waarschijnlijk de beste optie.


0
2017-12-11 16:55