LINUX.ORG.RU

[python] Помогите оптимизировать маленькую прогу, пж.

 


0

0

Я учусь кодить на Пайтоне. Если не трудно, покажите приемы оптимизации на данном примере. Скрипт рабочий. Если надо могу приложить еще образец файла, откуда все читается. К сожалению, некоторые отступы «поползли». Sorry.

#! /usr/bin/python
# -*- coding: utf-8 -*-
"""Файл-мэнеджер, обрабатывающий файлы Descript.ion, созданные программой FAR
Файлы раскодируются из DOS, выводится список файлов с их каментами, опция асинхронного запуска.
"""
from Tkinter import *
import codecs
import re
import os
import subprocess

root = Tk()

class wid:
    def __init__(self):

	fr = Frame(root)       # рисуем gui
        fr.pack(side=TOP)
	self.bt = Button(fr, text='Run', command = self.yak)
        self.bt.pack(side=LEFT)
        self.en = Entry(fr, width=70)
        self.en.pack(expand=NO, side=RIGHT)
	
    def yak(self):           # функция, выполняемая при нажатии кнопки run
	z = self.en.get()

	ss = re.compile(r"(^(\".*?\"|[^ ]*) (.*$))")   # отделяем имя файла от камента
	u = list(ss.match(z).groups())			# to do: это надо делать в начале глав. цикла...

	global f_name
	f_name = u[1].replace('"','')     #  вычищаем лишние кавычки

	img = ['jpg|JPG', 'gif|GIF', 'png|PNG', 'tiff|TIFF']     # файловые ассоциации
	vid = ['avi|AVI', 'mpg|MPG']

	def check(ls):		# функция проверки расширения файлов
	    
	    ext = f_name[-3:]   # вырезаем расширение из имени файла
	    for y in ls:	# обходим переданный список расширений
		t = re.compile(y)
		if t.match(ext):    # если расширение соответствует паттерну
		    w = os.getcwd() + '/' + f_name	# выводим путь
		    break
		else:
		    w = 0
	    return w

	wls = []	# список аргументов для передачи объекту Popen

	if check(img) != 0:     # если check нашел расширение и вернул путь к файлу
	    wls.append('feh')	# делаем список для запуска в ком. строке
	    wls.append(check(img))
#	    print wls
      	    subprocess.Popen(wls)    # обработка списка (модуль subprocess)
#	else:  # здесь должно быть исключение. лучше try - except

#subprocess
#	    print 'img'
	else:
	    if check(vid) != 0:
		wls.append('mplayer')	# делаем список для запуска в ком. строке
		wls.append(check(vid))
#		print wls
		subprocess.Popen(wls)    # весь кусок после wls = [] - в объект. Не всем типам файлов нужен
					    # асинхронный запуск...

#	else:  # здесь должно быть исключение. лучше try - except

###################### MAIN ############################

try:
    fp = codecs.open('./Descript.ion', "rb", "cp866")	# читаем файло
    l = fp.read()
    p = l.split("\n")
    fp.close
except:
    print "no desc file found"
some = []
for i in range(len(p) - 1):	# построчная обработка списка. Главный цикл.
    some.append(wid())		# добавляем экземпляры класса, содержащего кнопку и поле ввода
    some[i].en.insert(0, p[i].rstrip())    # пишем в поле текст из строки

root.mainloop()    

# to do: 1 стоит здесь (в главном цикле) разделить имя файла и камент. То и другое - globals
# 2 добавить вывод ls (опционально вывод только откомментированных файлов)
# 3 сохранение файла описания в файл utf8 (desc.utf). при старте поиск этого файла, затем 
# поиск старого файла Descript.ion
# 4 забить каменты в базу (lightSQL?), поиск по базе каментов.

★★

Дай подумать.
В петоне можно засовывать разную мелочь на стек? Нет. В петоне есть декларации типов? Нет. В петоне есть макросы, для кодогенерации и компайл-тайм вычислений? Нет.
Как нет там, в этом убожестве, и многого другого. В петоне мало что оптимизировать можно.

guest-3484-2009
()
Ответ на: комментарий от frpaul

Короче, этот как код переписать на python, чтобы было Ъ?

frpaul ★★
() автор топика

В коде много вещей, за которые я бил бы по рукам.

>К сожалению, некоторые отступы "поползли"

Это такой троллинг?

anonymous4
()

>Скрипт рабочий.

Это ты погорячился - вырезаешь расширение ext = f_name[-3:] - 3 символа, а в паттернах у тебя например tiff - 4 символа.

А вообще код говно. Лучше огласи что ты хотел написать и может кто-нибудь тебе напишет как надо с нуля - тогда ты поймешь где ты облажался.

imp ★★
()
Ответ на: комментарий от anonymous4

>В коде много вещей, за которые я бил бы по рукам.

Ну а зачем я все это выложил, спрашивается? Вот руки, вот розги :)
Хотя бы основные моменты.

>К сожалению, некоторые отступы "поползли"

>Это такой троллинг?


Не. В vim и gedit все нормально смотрится, а здесь уезжает почему-то. ЧЯДНТ?

frpaul ★★
() автор топика

Когда выкладываешь пример, потрудись сделать так, чтобы его можно было
скопипастить и запустить. Если лор жуёт твои отступы, используй dpaste
или что-то в этом духе.

Выбирай понятные названия переменных. `z`, `ss`, `u`, `w` — хер
проссышь.

> for i in range(len(p) - 1):

Как это вообще работает? p не видно же.

Весь код с `img`, `vid` и функцией `check` надо вынести из описания
виджета и переписать. Не должно быть явных проверок вроде

   check(img) != 0
   check(vid) != 0

`check` должна принимать имя файла и список проверяемых типов,
возвращая тип файла (каким-то символическим обозначением). Должна быть
другая функция, которая по типу файла и его имени (или просто по его
имени, вызывая внутри себя `check`) возвращает команду для запуска
этого файла. Должна быть возможность легко расширять библиотеку
известных типов, описывая соответствующие типу расширения и команду
для запуска, например:

    type_exts = {'img': ['jpg', 'gif', 'tiff'], 'vid': ['avi', '3gp', mov']}
    type_cmds = {'img': 'feh %s', 'vid': 'mplayer %s'}

Лучше так:

    ext = f_name.split('.')[-1]

По-хорошему, это приведёт к новой расширенной реализации модуля
mimetypes, поэтому лучше сразу используй его и всё.

> check(img) != 0

Здесь вам не C.

Ещё

else:
if:

заменить на

elif:

Комментарии, которые находятся на одной строке с кодом, очень плохи,
потому что находятся после кода, который описывают, затрудняют чтение
патчей, а также их неудобно редактировать. Описания функций лучше
вносить в строки документирования, например:

def check(file, types):
    """
    Проверить, соответствие `file` одному из типов, описанных в списке
    `types`, и вернуть название типа.
    """

В слове «менеджер» нет буквы «э».

Sphinx ★★☆☆
()
Ответ на: комментарий от frpaul

> Не. В vim и gedit все нормально смотрится, а здесь уезжает почему-то. ЧЯДНТ?

Возможно, у тебя в коде табы вперемешку с пробелами, а при копировании
каждый таб превратился в пробел? Хотя не знаю, как такое возможно.

Именно поэтому лучше использовать пробелы, а не табы.

Sphinx ★★☆☆
()
Ответ на: комментарий от imp

>Это ты погорячился - вырезаешь расширение ext = f_name[-3:] - 3 символа, а в паттернах у тебя например tiff - 4 символа.

Я это заметил. То же самое касается html. Значит опять регекспом вытаскивать?

>Лучше огласи что ты хотел написать и может кто-нибудь тебе напишет как надо с нуля - тогда ты поймешь где ты облажался.


Задача минимум:

1. Читать каменты к файлам в директории, которые хранятся в Descript.ion (кодировка DOS).
2. Запускать файлы в ассоциированных программах (ассоциации задаются внутри программы, не системные).
3. Конфигу в текстовый файл, отдельно, примерно как в mc (но необязательно).
4. Будьте мягче и к Вам потянутся люди ;)

frpaul ★★
() автор топика
Ответ на: комментарий от Sphinx

Sphinx, спасибо большое!

Буду исправлять.

frpaul ★★
() автор топика
Ответ на: комментарий от frpaul

> В vim и gedit все нормально смотрится, а здесь уезжает почему-то. ЧЯДНТ?

используешь символы табуляции вместо православных пробелов.

// К.О.

isden ★★★★★
()
Ответ на: комментарий от isden

>>используешь символы табуляции вместо православных пробелов.

Точно, я забыл конфигу vim'а поправить. На нетбуке нормально, а здесь фигня какая-то. Уже сделал по-человечески. Код перепОщу, когда исправлю ошибки.

frpaul ★★
() автор топика
Ответ на: комментарий от frpaul

>Я это заметил. То же самое касается html. Значит опять регекспом >вытаскивать?

os.path.splitext

kitov ★★★
()
Ответ на: комментарий от guest-3484-2009

> Как нет там, в этом убожестве, и многого другого. В петоне мало что > оптимизировать можно.

Какие мы 'лисперы' суровые ...

kitov ★★★
()
Ответ на: комментарий от frpaul

Добавлю к тому, что уже сказали, результаты своего беглого просмотра.

>class wid:

Олд-стайл классы использовать без нужды не стоит.

>self.bt = Button(fr, text='Run', command = self.yak)

Пробелы вокруг знака "=" не нужны        ^^^ вот тут. Да и вообще выкури PEP8, это пойдет сильно на пользу.

>def yak(self):           # функция, выполняемая при нажатии кнопки run
>def check(ls):      # функция проверки расширения файлов

Почему не докстринги?

>ext = f_name[-3:]   # вырезаем расширение из имени файла

Так нельзя. Тут уже посоветовали splitext.

>vid = ['avi|AVI', 'mpg|MPG']

Вместо такой мути стоит использовать метод строки lower().

>       for y in ls:   # обходим переданный список расширений
>      t = re.compile(y)

Но если уж это регэкспы, то переменную "y" неплохо было бы заэскейпить, нет?

>w = os.getcwd() + '/' + f_name   # выводим путь

Не надо конкатенировать элементы пути таким образом. Используй os.path.join

>#       print wls

Мусорные комментарии можно было бы и повычищать.

>###################### MAIN ############################

Это и дальше надо засунуть в блок if __name__ == '__main__':

>    fp = codecs.open('./Descript.ion', "rb", "cp866")   # читаем файло

Зачем './' в имени файла? Он и так будет из текущей рабочей директории читаться, если путь относительный. Или так специально ломаешь работоспособность под вендой? :)

>    l = fp.read()
>    p = l.split("\n")

Вообще-то есть splitlines, но даже без этого текстовый файл и так прекрасно итерируется по строкам.

>    fp.close

И ты думаешь ты здесь вызвал эту функцию?

>except:
>    print "no desc file found"

Нельзя подавлять все исключения. Никогда так не делай.

>    some[i].en.insert(0, p[i].rstrip())    # пишем в поле текст из строки

Плохая идея растить список с его "переднего конца". Лучше уж собрать список обычным .append() а потом сделать один раз .reverse()

А вообще если уж хочешь чтобы тебе сделали бесплатный код-ревью, хотя бы разберись с табами и пробелами и выкладывай на какой-нибудь paste-сервис, чтобы можно было на номера строк ссылаться.

anonymous4
()
Ответ на: комментарий от anonymous4

>> for y in ls: # обходим переданный список расширений
>> t = re.compile(y)


>Но если уж это регэкспы, то переменную "y" неплохо было бы заэскейпить, нет?


Что-то не соображу, как это сделать.

frpaul ★★
() автор топика
Ответ на: комментарий от anonymous4

> some[i].en.insert(0, p[i].rstrip()) # пишем в поле текст из строки

>Плохая идея растить список с его "переднего конца". Лучше уж собрать список обычным .append() а потом сделать один раз .reverse()


Вы действительно "по диагонали" прочитали. insert здесь - не метод списка, а гуевого en (Entry). Просто строка из файла вставляется. Спасибо, буду иметь в виду: нужно внимательно смотреть к чему относится метод.

frpaul ★★
() автор топика

по поводу расширений и прочего есть os.path а именно, `splitext` да и прочее, что обеспечивает кроссплатформенность в вопросе путей.

вообще, запости нормально на pastie.org, тогда и разобраться проще будет. а то мешанина какая то.

проверить расширение можно многими способами, например по dict, str.endswith и прочими.

списковые включения быстрее и понятнее простых циклов, например:

[ i for i in [0,0,1,3,4,0,0] if i]

Apkawa
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.