2015-05-01 2 views
1

Я пишу отличный сценарий, и все мы должны удалить все операторы печати из файлов python в каталоге/или в одном файле python, прежде чем делать рулон кода. У меня есть printremover.py:ошибка удаления печати с ошибкой

def read_content_to_linelist(the_file): 
    try: 
     f = file(the_file, 'r') 
     content = f.readlines() 
     f.close() 
     return content 
    except IOError: 
     return 0 

def remove_print(linelist): 
    string = "" 
    for line in linelist: 
     if re.match(r"^\s*print.*", line): 
      linelist.remove(line) 
     else: 
    for line in linelist: 
     string += line 
    return string 

Я играл с файла fake.py в то время как я проверить:

name = 'cody' 

print name 
print 'cody' 
print 4 

когда я печатаю список из read_content_to_linelist, я получаю хорошие данные. Но когда я удаляю_принт, я получаю все правильно, за исключением того, что по какой-то причине оставляет print 'cody'. Он оставляет переменную и удаляет другие 2 отпечатка.

+0

Как насчет отпечатков в функциях? –

+0

Что значит? – codyc4321

+0

. он дает мне '['#!/user/bin/env python \ n', '# coding: utf-8 \ n'," name = 'cody' \ n ", '\ n', 'print name \ n ', "print' cody '\ n",' print 4 '] ', но когда я печатаю строку за строкой в ​​цикле for, она пропускает" print' cody \ n "каждый раз, считая до 6, когда есть 7 линий. Я проверяю строки в remove_print непосредственно перед циклом for – codyc4321

ответ

1

В remove_print, первый цикл должен быть:

for line in linelist[:]: 
    ... 

Это создает копию linelist, которая необходима, если он модифицируется внутри цикла.

Кроме того, ваш else может (должен) быть опущен, так как в нем ничего не происходит.

Другое примечание: вашему регулярному выражению не нужна ведущая каретка (^), так как re.match проверяет начало строки; вам понадобится только каретка с re.search.

+0

Ответы были проще и проще понять, спасибо вам всем. Я вижу сейчас – codyc4321

+0

Это неэффективно. Вы создаете копию списка, чтобы избежать ошибки, но код не требует изменения списка в первую очередь. Вы соединяете хорошие строки в строке. Список не используется, поэтому удаление неправильных строк не требуется. –

1

Вместо этого вы должны использовать re.sub. Когда вы remove от list, тогда заказ будет изменен. В цикле for

  1. первый элемент удаляется.

  2. Второй элемент - первый, третий на втором.

  3. for Счетчик циклов находится на втором, но элемент изменился.

Непосредственно использовать

print re.sub(r"^\s*print.*$","",x,flags=re.MULTILINE) 

где x является f.read()

1

Ваша проблема заключается в том, что вы изменяете список, как вы петлю над ним. Ваша логика может быть значительно упрощена с помощью встроенного в filter и join функции:

def read_content_to_linelist(the_file): 
    try: 
     f = file(the_file, 'r') 
     content = f.readlines() 
     f.close() 
     return content 
    except IOError: 
     return 0 

def good_line(line): 
    return not re.match(r"\s*print.*", line) 

def remove_print(linelist): 
    good_lines = filter(good_line, linelist) 
    return ''.join(good_lines) 
+0

Прошу прощения, я попробовал, и это не сработало. – codyc4321

+0

Что не сработало? Это сработало для меня. Я сделал 'lines = read_content_to_linelist (« fake.py »)' then' print remove_print (lines) ', и я получил только строку' name = 'cody'' и пустую строку. –

+0

У меня ошибка в коде. Позвольте мне снова проверить Джейка – codyc4321

1

Вы можете использовать unparser.py с модулем Аст для удаления отпечатков:

import inspect 
import importlib 
import ast 
from unparser import Unparser # unparser.py 

class RemovePrint(ast.NodeTransformer): 
    def __init__(self): 
     self.count = 0 
    def visit_Print(self, node): 
     self.count += 1 
     print("Removed {} print/s".format(self.count)) 
     self.generic_visit(node) 
    return None 




mod = "yourfile" 
mod = importlib.import_module(mod) 
p = ast.parse(inspect.getsource(mod)) 

t = RemovePrint().visit(p) 
print(ast.dump(p)) 
Module(body=[Assign(targets=[Name(id='name', ctx=Store())], `value=Str(s='cody')), FunctionDef(name='foo', args=arguments(args=[Name(id='x', ctx=Param())], vararg=None, kwarg=None, defaults=[]), body=[AugAssign(target=Name(id='x', ctx=Store()), op=Add(), value=Num(n=4)), Return(value=Name(id='x', ctx=Load()))], decorator_list=[]), ClassDef(name='Foo', bases=[], body=[FunctionDef(name='__init__', args=arguments(args=[Name(id='self', ctx=Param())], vararg=None, kwarg=None, defaults=[]), body=[Assign(targets=[Attribute(value=Name(id='self', ctx=Load()), attr='foo', ctx=Store())], value=Str(s='foo'))], decorator_list=[])], decorator_list=[])]`) 


Unparser(p, open("temp_test.py", "w")) 

нужен немного работы, но выходы :

name = 'cody' 

def foo(x): 
    x += 4 
    return x 

class Foo: 

    def __init__(self): 
     self.foo = 'foo' 
' 

От:

name = 'cody 
print name 
print 'cody' 
print 4 


def foo(x): 
    x += 4 
    print x 
    return x 


class Foo: 
    def __init__(self): 
     self.foo = "foo" 
     print("foo") 

Это не сработает с использованием python3 и проверяется только с помощью python2.7, я добавлю код python3, когда я его заработаю.

Смежные вопросы