Уведомления

Группа в Telegram: @pythonsu

#1 Дек. 3, 2013 19:17:06

agryn
От: Украина
Зарегистрирован: 2011-12-14
Сообщения: 189
Репутация: +  0  -
Профиль   Отправить e-mail  

Прерывание цыкла генератора

Есть очень большой (или просто большой) /etc/passwd файл, нужно из него очень быстро извлечь username по uid.
Быстро читать конечно нужно с помощью генератора. Но если например запись с самого начала то не оптимально далее дочитывать строки. От сюда вопрос как можно после получения первого значения прекратить/прервать генератор (по аналогии как это делается breack в простом цикле)?

def get_usrname(user_uid):
    passwd_file = open('/etc/passwd')
    user_name_list = [passwd_file_line.split(':')[0] for passwd_file_line in passwd_file if passwd_file_line.split(':')[2] == user_uid]
    return user_name_list[0]
"""
## example /etc/passwd
psaftp:x:505:506:anonftp psa user:/:/sbin/nologin
apache:x:506:507:Apache server:/:/sbin/nologin
drweb:x:100:511:DrWeb system account:/var/drweb:/bin/false
webalizer:x:67:67:Webalizer:/var/www/usage:/sbin/nologin
mailman:x:41:41:GNU Mailing List Manager:/usr/lib/mailman:/sbin/nologin
ntp:x:38:38::/etc/ntp:/sbin/nologin
named:x:25:25:Named:/var/named:/sbin/nologin
sw-cp-server:x:507:512::/:/bin/true
paveln:x:10000:509::/var/www/vhosts/localhost.localdomain:/bin/false
nginx:x:498:497:Nginx user:/var/lib/nginx:/bin/false
test3:x:10001:10001::/home/test3:/bin/bash
test4:x:10002:10002::/home/test4:/bin/bash
testuser:x:10003:10003::/home/testuser:/bin/bash
testuser1:x:10003:10004::/home/testuser:/bin/bash
"""

Отредактировано agryn (Дек. 3, 2013 20:14:40)

Офлайн

#2 Дек. 3, 2013 20:49:07

Rodegast
От: Пятигорск
Зарегистрирован: 2007-12-28
Сообщения: 2751
Репутация: +  184  -
Профиль   Отправить e-mail  

Прерывание цыкла генератора

Я так и не понял в чём у тебя проблема?

def get_usrname(user_uid):
	for x in open('/home/rodegast/pass'):
		if x.split(':')[2] == user_uid:
			return x.split(':')[0]
print get_usrname("505")
Или как то так отфильтровать можно:
user_uid = "506"
print map(lambda x: x.split(':')[0], filter(lambda x:x.split(':')[2] == user_uid, open('/home/rodegast/pass')))



С дураками и сектантами не спорю, истину не ищу.
Ели кому-то правда не нравится, то заранее извиняюсь.

Офлайн

#3 Дек. 4, 2013 15:00:03

agryn
От: Украина
Зарегистрирован: 2011-12-14
Сообщения: 189
Репутация: +  0  -
Профиль   Отправить e-mail  

Прерывание цыкла генератора

Rodegast
def get_usrname(user_uid):
	for x in open('/home/rodegast/pass'):
		if x.split(':')[2] == user_uid:
			return x.split(':')[0]
Вот этот код нужно с помощью генератора для большой скорости.

Офлайн

#4 Дек. 4, 2013 15:25:24

PooH
От:
Зарегистрирован: 2006-12-05
Сообщения: 1948
Репутация: +  72  -
Профиль   Отправить e-mail  

Прерывание цыкла генератора

agryn
Вот этот код нужно с помощью генератора для большой скорости.
Не знаю уж, какой скорости вы хотите добиться на сотне строк файла паролей. Но вам дали правильные вариант - файл читается построчно, до первого включения, а у вас как раз весь считывается в список :P
ну или, если хотите, в более функциональном стиле:
def first(ls, test):
    for x in ls:
        if test(x):
            return x
def get_username(search_uid):
    with open('/etc/passwd') as inf:
        return first((passwd_file_line.split(':') for passwd_file_line in inf), lambda x: x[0] == search_uid)



Вот здесь один из первых отарков съел лаборанта. Это был такой умный отарк, что понимал даже теорию относительности. Он разговаривал с лаборантом, а потом бросился на него и загрыз…

Отредактировано PooH (Дек. 4, 2013 15:28:08)

Офлайн

#5 Дек. 4, 2013 15:56:25

Budulianin
От:
Зарегистрирован: 2011-10-18
Сообщения: 1218
Репутация: +  33  -
Профиль   Отправить e-mail  

Прерывание цыкла генератора

agryn
Вообще-то генератор списков это просто “синтаксический сахар” и по реализации ничем не отличается, от обычного for. Следовательно он работает с такой же скоростью.

lst = []
for elem in xrange(10):
    lst.append(elem)

тоже самое
lst = [elem for elem in xrange(10)]

Или генератор списков это выражение генератор преобразованный в список при помощи list ?



Отредактировано Budulianin (Дек. 4, 2013 16:31:56)

Офлайн

#6 Дек. 4, 2013 15:59:56

smoke853
Зарегистрирован: 2012-10-02
Сообщения: 123
Репутация: +  15  -
Профиль   Отправить e-mail  

Прерывание цыкла генератора

может вместо return использовать yield ? Может автор темы эту быстроту имеет ввиду?
http://savepic.ru/4976932.jpg

Офлайн

#7 Дек. 4, 2013 16:00:53

Budulianin
От:
Зарегистрирован: 2011-10-18
Сообщения: 1218
Репутация: +  33  -
Профиль   Отправить e-mail  

Прерывание цыкла генератора

smoke853
может вместо return использовать yield ? Может автор темы эту быстроту имеет ввиду?

Какая от этого скорость? Так только памяти меньше ест



Офлайн

#8 Дек. 4, 2013 16:07:57

sergeek
Зарегистрирован: 2012-06-26
Сообщения: 470
Репутация: +  43  -
Профиль   Отправить e-mail  

Прерывание цыкла генератора

comprehension'ы оптимизируют как раз-таки полную генерацию списка и было бы грубо требовать от них наличие break'а.
Раз уж фп-тред

import operator as op
 
split = lambda sep : lambda string : string.split(sep)
 
def find(item, seq, test=op.eq, key=lambda elt : elt):
    for elt in seq:
        if test(item, key(elt)):
            return elt
            
def get_username(uid):
    return find(uid,
                map(split(':'),
                    open('/etc/passwd')),
                key=op.itemgetter(2))[0]
 
print(get_username('10'))

Офлайн

#9 Дек. 4, 2013 16:08:26

smoke853
Зарегистрирован: 2012-10-02
Сообщения: 123
Репутация: +  15  -
Профиль   Отправить e-mail  

Прерывание цыкла генератора

В смысле какая скорость? в первом случае время выполнения = 0.755, во втором = 0.002, очевидно что второй вариант работает быстрее.

Офлайн

#10 Дек. 4, 2013 16:18:42

flip89
От:
Зарегистрирован: 2011-10-21
Сообщения: 28
Репутация: +  2  -
Профиль   Отправить e-mail  

Прерывание цыкла генератора

smoke853
В смысле какая скорость? в первом случае время выполнения = 0.755, во втором = 0.002, очевидно что второй вариант работает быстрее.
Долго думал, где же подвох)



Офлайн

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version