About Blog |

подсчет числа файлов в каталоге

ls | tee /dev/stderr | wc -l
find -type f|cat -n

Блокировка записей в реляционных БД

Блокировка при использовании реляционных БД.
Если вы используете реляционные базы данных, можно использовать "LOCK" механизм для блокировки доступа к критичным секциям.
В то время когда одна "SELECT FOR UPDATE" транзакция лочит строку, другая "SELECT FOR UPDATE" с этой строкой будет ждать конца 1 транзакции.
# You can use any Python DB API.
[SQL] BEGIN;
[SQL] SELECT col_name FROM table_name where id = 1 FOR UPDATE;

[Process some python code]

[SQL] COMMIT;

блокировка критичных секций в python

  1 import os
  2
  3 class SingleRun():
  4     class InstanceRunningException(Exception):
  5         pass
  6     def __init__(self, lock_file):
  7         #define the lock file name
  8         self.lock_file =  "/tmp/%s.pid" % lock_file
  9     def __call__(self, func):
 10         def f(*args, **kwargs):
 11             if os.path.exists(self.lock_file):
 12                 #get process id, if lock file exists
 13                 pid = open(self.lock_file, "rt").read()
 14                 if not os.path.exists("/proc/%s" % pid):
 15                     #if process is not alive remove the lock file
 16                     os.unlink(self.lock_file)
 17                 else:
 18                     #process is running
 19                     raise self.InstanceRunningException(pid)
 20             try:
 21                 #store process id
 22                 open(self.lock_file, "wt").write(str(os.getpid()))
 23                 #execute wrapped function
 24                 func(*args,**kwargs)
 25             finally:
 26                 if os.path.exists(self.lock_file):
 27                     os.unlink(self.lock_file)
 28         return f


Пример

  1 @SingleRun(lock_file="x")
  2 def a():
  3     pass
  4
  5 @SingleRun(lock_file="x")
  6 def b():
  7     pass
  8
  9 @SingleRun(lock_file="y")
 10 def c():
 11     pass
http://krosinski.blogspot.com/2012/04/preventing-python-script-from-running.html
http://stackoverflow.com/questions/1123200/how-to-lock-a-critical-section-in-django
http://code.activestate.com/recipes/519626/
import os
import fcntl

class DjangoLock:

    def __init__(self, filename):
        self.filename = filename
        # This will create it if it does not exist already
        self.handle = open(filename, 'w')

    # flock() is a blocking call unless it is bitwise ORed with LOCK_NB to avoid blocking 
    # on lock acquisition.  This blocking is what I use to provide atomicity across forked
    # Django processes since native python locks and semaphores only work at the thread level
    def acquire(self):
        fcntl.flock(self.handle, fcntl.LOCK_EX)

    def release(self):
        fcntl.flock(self.handle, fcntl.LOCK_UN)

    def __del__(self):
        self.handle.close()

Usage:

lock = DJangoLock('/tmp/djangolock.tmp')
lock.acquire()
try:
    pass
finally:
    lock.release()

python else

В питоне else применим не только для if, но также и для for и try.
for i in foo:
    if i == 0:
        break
else:
    print("i was never 0. Вызов будет если break не был вызван")

same as:

found = False
for i in foo:
    if i == 0:
        found = True
        break
if not found: 
    print("i was never 0")
try:
  do()
except Exception:
  print "Catch!"
else:
  print "Если не был пойман эксепшен - выполнится этот код внутри else!"
finally:
  end()

списочные выражения на python

foo = [x for x in xrange(10) if x % 2 == 0]

#same as 

foo = []
for x in xrange(10):
  if x % 2 == 0:
     foo.append(x)
#set
{x for x in stuff}

#dicts python 2.7
{ a:a for a in range(10) }
[(i,j) for i in range(3) for j in range(i) ]    

Тоже что

for i in range(5):
	for j in range(i):
		print i,j
# if + nested for
[(x, y) for x in range(4) if x % 2 == 1 for y in range(4)]
[(1, 0), (1, 1), (1, 2), (1, 3), (3, 0), (3, 1), (3, 2), (3, 3)]

Как реализуется многозадачность

Переключение задач реализуется на программном уровне следующим образом: Ставится код на таймер который анализирует зарегистрированные в системе процессы. Далее он выбирает нужный процесс, сохраняет текущий (все регистры), загружается состояние выбранного на исполнение процесса и возвращается Iret - ом на выбранный вновь процесс. Далее опять по таймеру он прерывается, сохраняется и выбирается следующий на исполнение процесс. Структуры процессов отличаются в зависимости от ОС.
Ядро может переключить задачу в след случаях:
-закончился квант отведенный задаче
-задача запросила доступ к ресурсу (I/O) ее нада усыпить пока придет ответ
ссылки:
http://tldp.org/HOWTO/KernelAnalysis-HOWTO-6.html
habrahabr.ru/post/120685/

tsl (test and set) — как реализованы locks

Locks используемые для одновременного закрытия доступа процессов к одним и тем же ресурсам, Реализованы на ассемблере следующим образом, с помощью атомарной операции tsl - test and set:
enter_region:        ; A "jump to" tag; function entry point.
  tsl reg, flag      ; Test and Set Lock
  cmp reg, #0        
  jnz enter_region  
  ret                  
Основную работу тут делает атомарная операция (она не может быть прервана) tsl: Переменная flag копируется в регистр reg и если flag равен 0 устанавливается в 1 (атомарная операция) Атомарность гарантирует что контекст не будет переключен на другие процессы и они не войдут в защищаемую от совместного доступа область.
Вот как определяет это википедия: Test-and-set — простая неразрывная (атомарная) процессорная инструкция, которая копирует значение переменной в регистр, и устанавливает некое новое значение. Во время исполнения данной инструкции процессор не может прервать её выполнение и переключится на выполнение другого потока. Если используется многопроцессорная архитектура, то пока один процессор выполняет эту инструкцию с ячейкой памяти, то другие процессоры не могут получить доступ к этой ячейке, может достигаться путем кратковременного блокирования шины памяти.
  enter_critical_section:
  TSL REGISTER, LOCK // Значение переменной LOCK копируется в регистр
                        // и устанавливается в 1.
     CMP REGISTER, #0   // Старое значение сравнивается с нулем.
     JNE enter_critical_section // Если оно ненулевое, значит кто-то уже вошел в критическую секцию и заблокировал её.
    
     RET                // Блокировка выполнена успешно, возвращаемся в вызывающую функцию.
При этом разблокирование ячейки производится обычной процедурой MOV:
  leave_critical_section:
     MOV LOCK, #0   // Разблокирование переменной. 
     RET            // Возврат в вызывающую функцию.

Подобное поведение может быть реализованно не только аппаратно, но и на программном уровне сущесьвуют следующие алгоритмы:
Dekker's algorithm
Peterson Lamport Также по теме: Fast Userlevel Locking http://stackoverflow.com/questions/1726702/how-are-mutex-and-lock-structures-implemented http://stackoverflow.com/questions/1485924/how-are-mutexes-implemented

python генераторы и итераторы

iterator это объект чей класс имеет next метод и __iter__ метод который возвращает сам объект.
применение итераторов
Перечисление различных последовательностей (с генерацией или без). Вы можете генерировать последовательности не используя память для их хранения. Пример:
class Squares(object):
    def __init__(self, start, stop):
       self.start = start
       self.stop = stop
    def __iter__(self): return self
    def next(self):
       if self.start >= self.stop:
           raise StopIteration
       current = self.start * self.start
       self.start += 1
       return current
Для более локаничного написания итераторов в питоне используются генераторы, те генератор это способ имплементации итератора. Генератор можно задать несколькими способами:
# генератор аналогичный итератору приведенному выше 
def squares(start, stop):
    for i in xrange(start, stop):
        yield i * i

for i in squares(1,4): print i

# или еще более локанично 
# generator expression
gen = (i*i for i in xrange(1, 4))
for i in gen: print i

ссылки по теме. http://www.python.org/dev/peps/pep-0289/
http://stackoverflow.com/questions/2776829/difference-between-python-generators-vs-iterators
про то как они устроены неплохо описано тут:
http://python.su/forum/topic/7150/

добавляем генератор уникальных чисел к request в django

Часто в шаблонах нужно бывает получить уникальный ид для обозначения какого либо блока.
Полезная вещь для этого: в миддлваре подмодифицируем request, добавив к нему метод который содержит генератор чисел. ...
#django uniq numbers generator in request (accessable in templates)
    def gen_uniq():
        i=0
        while True:
            i=i+1
            yield "uniq%d" % i
    gen = gen_uniq()
    def gen_method(self):
        return gen.next()
        
    request.gen_uniq = types.MethodType( gen_method, request )
далее в шаблонах просто достаем: request.gen_uniq

смотрим что висит на портах

sudo netstat -ntap или sudo lsof -i :80 # по lsof отлич мануал http://handynotes.ru/2010/01/unix-utility-lsof.html sudo lsof -nPi #показывается что слушается и куда подконекчено n-включает адреса вместо имен -P включает номера портов вместо скоращений, i - это сетевые сокеты Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name tcp 0 0 127.0.0.1:3306 0.0.0.0:* LISTEN 944/mysqld tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 1129/apache2 tcp 0 0 127.0.0.1:631 0.0.0.0:* LISTEN 1039/cupsd tcp 0 0 192.168.1.2:34613 64.12.30.109:443 ESTABLISHED 2477/pidgin tcp 0 0 192.168.1.2:48571 173.194.69.113:443 TIME_WAIT - tcp 0 453 192.168.1.2:53750 173.194.69.139:80 ESTABLISHED 12821/firefox tcp 0 0 192.168.1.2:60069 91.189.89.114:443 ESTABLISHED 2427/python tcp6 0 0 ::1:631 :::* LISTEN 1039/cupsd ------------------------------- -n Показывать сетевые адреса как числа. netstat обычно показывает адреса как символы. Эту опцию можно использовать с любым форматом показа. -p Отобразить идентификатор/название процесса создавшего сокет (-p, --programs display PID/Program name for sockets) -a Показывать состояние всех сокетов; обычно сокеты, используемые серверными процессами, не показываются. -t Another useful netstat option is -t, which shows all active TCP connections.