Архив рубрики: Python

Потоки на Python

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

#!/usr/local/bin/python
# coding=utf-8
import threading
import time

debug=True
#количество одновременно запускаемых потоков
thread_count=10;

def putlog(txt):
    if (debug==True):
     print txt
def worker(th):
    putlog("--стартовал поток "+str(th));
    i=0
    while i<config.thread_count:
     putlog("--поток "+str(th)+", шаг "+str(i))
     time.sleep(1)
     i=i+1
def main():
    putlog("-скрипт стартовал!");    
    #запускаем потоки
    for i in xrange(thread_count):
	thread = threading.Thread(target=worker, args=(i,)).start()	
    #ждем пока потоки завершатся	
    while threading.active_count() >1:
     putlog("!ждем завершения потоков")	
     time.sleep(1)
    putlog("-скрипт закончил работу!");	 
main()

Результат работы скрипта:

-скрипт стартовал!
--стартовал поток 0
--поток 0, шаг 0
--стартовал поток 1
--поток 1, шаг 0
--стартовал поток 2
 !ждем завершения потоков
--поток 2, шаг 0
--поток 0, шаг 1
!ждем завершения потоков
--поток 1, шаг 1
--поток 2, шаг 1
--поток 0, шаг 2
!ждем завершения потоков--поток 1, шаг 2

--поток 2, шаг 2
!ждем завершения потоков
-скрипт закончил работу

Отправка сообщения на email по smtp, в utf8 с телом в html

import smtplib   
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart

		 msg = MIMEMultipart('alternative')
		 html_body="Внимание! У вас есть задача (№"+str(id)+") в sbss, которая уже длительное время находится в статусе ожидания! Через 3 дня она будет автоматически закрыта.. <br/><a href=https://oeirfoeriferoife.ru>"+name+"</a>".encode('utf-8')
		 msg.set_charset("utf-8")
		 msg['Subject'] = "Уведомление о длительной задаче №"+str(id);
		 msg['From'] = sbss_from_email
		 msg['To'] = m_arr["email"]		 
		 part = MIMEText(html_body, 'html', 'UTF-8')
		 msg.attach(part)
		 s = smtplib.SMTP(sbss_from_server)
		 s.login(sbss_from_email,sbss_from_pass);
		 s.set_debuglevel(1);
		 s.sendmail(sbss_from_email, m_arr["email"], msg.as_string())
		 s.quit()

Python и ошибка InternalError(-1, ‘Unread result found.’, None))

Сия ошибка возникает когда одно и тоже соединение используется в «вложенных» запросах.  Хотя курсоры разные. Т.е. внутри проходу по циклу cursor.fetchone(), выполняется еще один запрос с этим же идентификатором соединения, но с другим курсором.

Решение: курсор создаем с «буфером»: cursor = sbss.cursor(dictionary=True,buffered=True)

Например:

	sql="select * from requests where datediff(now(),lastpost)=%s-3 and statusid=3";
	cursor = sbss.cursor(dictionary=True,buffered=True)
	cursor.execute(sql,[sbss_from_count_days]);
	row = cursor.fetchone()	
	while row is not None:
	    id=row["id"];	
	    author_id=row["author_id"];	
	    responsible_man=row["responsible_man"];	
	    name=row["name"];		    
	    func.putlog("----нашли близкий к просрочке requests :"+str(id))	    	    
	    m_arr=func.GetSBSSManagerInfo(sbss,responsible_man);
	    row = cursor.fetchone()

Python и аргументы командной строки

В питоне есть два способа получения аргументов запуска скрипта из командной строки:

  1. Использовать модуль argparse. Попробовал. Не понравилось, потому что — это еще одна дополнительная зависимость в скрипте, что мне сильно не нравится, когда шапка простого скрипта забита десятком строк import с модуля которых нет в «базе», что нервирует когда запускаешь первый раз скрипт на системе с «голым» питоном. Для желающих, вот например хорошая статья
  2. Использовать стандартный модуль sys. Менее «навороченный», но и хотяб документацию не нужно «переваривать» с пол часа. И так всё понятно и стандартно.

Итак, пример скрипта:

# -*- coding: utf-8 -*-
import socket
import sys
import mysql.connector
from mysql.connector import Error


#настройки скрипта
vr="1.0"
hostdb="localhost"
database="grib"
userdb="root"
passdb="";


#выводим имя ПК и версию скрипта                
hostname = socket.gethostname()
print ("Server: ",hostname);
print ("Version: ",vr);

#разбираем коммандную строку

if len(sys.argv)>=3: 
   liscnt=sys.argv[2]
else:
    print ("Параметры запуска:")
    print ("-n XX  - количество выводимых строк в запросе")
    exit(0)
#пробуем соедениться с mysql
try:
    conn = mysql.connector.connect(host=hostdb,database=database,user=userdb,password=passdb)
    if conn.is_connected(): print('Вроде соеденился!')
except Error as e:
    print("Ошибка: ",e);
    exit(0);    

#создаем курсор запроса, с выводом имен столбцов
cursor = conn.cursor(dictionary=True)
try:
    cursor.execute("SELECT * FROM wp_posts limit "+liscnt);
    row = cursor.fetchone()
    while row is not None:
        print(row['post_title'])
        row = cursor.fetchone()
    conn.close()
except Error as e:
    print("Ошибка выполнения SQL: ",e);
    exit(0);    

Выборка из базы на python с именованными ячейками.

На php я привык, что результат запроса от базы данных, всегда приходит в именованном массиве. На python  это по не понятной причине по умолчанию не так. Вот как выглядит код для получения именованного массива на python:

# -*- coding: utf-8 -*-
import mysql.connector
from mysql.connector import Error
                
name='Павел';
print("Hello ",name);

try:
    conn = mysql.connector.connect(host='localhost',database='grib',user='root',password='')
    if conn.is_connected(): print('Вроде соеденился!')
except Error as e:
    print(e);
    exit(0);    

cursor = conn.cursor(dictionary=True)
cursor.execute("SELECT * FROM wp_posts");
row = cursor.fetchone()
while row is not None:
    print(row['post_title'])
    row = cursor.fetchone()
conn.close()