Область видимости переменной

arshanskiyav

Новичок
Пользователь
Май 17, 2020
3
0
1
Доброго времени.

ОС: ARMbian (Debian buster)
Python: 2.17.16

Имею опыт в скриптовых языках и 1С. Встала задача, которую решить при помощи python проще и быстрее.
Задача: мониторить изменение пина (GPIO) и запускать/отключать мигание светодиода (4 кнопки, 4 светодиода). Решил делать при помощи потоков и очередей.
Сделал, НО, основываясь на опыте и статье https://python-scripts.com/scope я не могу понять почему код работает в этом виде, как поток понимает что конкретно сейчас обновилась именно его очередь, если имена одинаковые (runJob):
Python:
#!/usr/bin/env python
import SUNXI_GPIO as GPIO
import time
import logging
from threading import Thread
from Queue import Queue

def blink_led(runJob,RED_LED,GREEN_LED,NameLED):
    nowJob=False
    logging.basicConfig(filename="blink_led.log", level=logging.INFO)
    while True:
        if runJob.empty() == False:
            nowJob=runJob.get()
            if nowJob is None:
                break
            logging.info(nowJob)
        if nowJob==True:
            logging.info(nowJob)
            GPIO.output(RED_LED, GPIO.HIGH)
            time.sleep(1)
            GPIO.output(GREEN_LED, GPIO.HIGH)
            time.sleep(1)
            GPIO.output(RED_LED, GPIO.LOW)
            time.sleep(1)
            GPIO.output(GREEN_LED, GPIO.LOW)
            time.sleep(1)
        else:
            GPIO.output(GREEN_LED, GPIO.LOW)
            GPIO.output(RED_LED, GPIO.LOW)

def check_button(runJob,IN_KEY,NameKey):
    stateJob=False
    while True:
        state=True #Checking that state pin GPIO do not has changed (contact bounce)
        if GPIO.input(IN_KEY) == False:
           state=False
           time.sleep(0.1)
           if  GPIO.input(IN_KEY) == state:
                print 'Key '+NameKey+' pressed.'
                if stateJob == False:
                    runJob.put(True)
                    stateJob=True
                    print 'runJob_'+NameKey
                else:
                    runJob.put(False)
                    stateJob=False
                    print 'StopJob_'+NameKey
                print stateJob
#BLOCK_1
# RED_LED = GPIO.PD9
# GREEN_LED = GPIO.PD8
# IN_KEY = GPIO.PD0
#BLOCK_2
# RED_LED = GPIO.PD11
# GREEN_LED = GPIO.PD10
# IN_KEY = GPIO.PD1
#BLOCK_3
# RED_LED = GPIO.PD113
# GREEN_LED = GPIO.PD12
# IN_KEY = GPIO.PD2
#BLOCK_4
# RED_LED = GPIO.PD115
# GREEN_LED = GPIO.PD14
# IN_KEY = GPIO.PD3
GPIO.init()
GPIO.setcfg(GPIO.PD0, GPIO.IN)
GPIO.setcfg(GPIO.PD1, GPIO.IN)
GPIO.setcfg(GPIO.PD2, GPIO.IN)
GPIO.setcfg(GPIO.PD3, GPIO.IN)

GPIO.setcfg(GPIO.PD8, GPIO.OUT)
GPIO.setcfg(GPIO.PD9, GPIO.OUT)
GPIO.setcfg(GPIO.PD10, GPIO.OUT)
GPIO.setcfg(GPIO.PD11, GPIO.OUT)
GPIO.setcfg(GPIO.PD12, GPIO.OUT)
GPIO.setcfg(GPIO.PD13, GPIO.OUT)
GPIO.setcfg(GPIO.PD14, GPIO.OUT)
GPIO.setcfg(GPIO.PD15, GPIO.OUT)


runJob=Queue(1)
ButtonJob_1 = Thread(target=check_button, args=(runJob,GPIO.PD0,'1',))
LedJob_1 = Thread(target=blink_led, args=(runJob,GPIO.PD9,GPIO.PD8,'1',))
ButtonJob_1.start()
LedJob_1.start()

runJob=Queue(1)
ButtonJob_2 = Thread(target=check_button, args=(runJob,GPIO.PD1,'2',))
LedJob_2 = Thread(target=blink_led, args=(runJob,GPIO.PD11,GPIO.PD10,'2',))
ButtonJob_2.start()
LedJob_2.start()

runJob=Queue(1)
ButtonJob_3 = Thread(target=check_button, args=(runJob,GPIO.PD2,'3',))
LedJob_3 = Thread(target=blink_led, args=(runJob,GPIO.PD13,GPIO.PD12,'3',))
ButtonJob_3.start()
LedJob_3.start()

runJob=Queue(1)
ButtonJob_4 = Thread(target=check_button, args=(runJob,GPIO.PD3,'4',))
LedJob_4 = Thread(target=blink_led, args=(runJob,GPIO.PD15,GPIO.PD14,'4',))
ButtonJob_4.start()
LedJob_4.start()

while True:
    time.sleep(1)
runJob.put(None)
LedJob_1.join()
ButtonJob_1.join()
LedJob_2.join()
ButtonJob_2.join()
LedJob_3.join()
ButtonJob_3.join()
LedJob_4.join()
ButtonJob_4.join()

Собственно вопрос - как поток определяет что сейчас обновилась именно его переменная?

Спасибо.
 

MaksimD

Пользователь
Пользователь
Май 12, 2020
51
11
8
Собственно вопрос - как поток определяет что сейчас обновилась именно его переменная?

Спасибо.

Поток ничего не опредиляет - он просто выполняется центральным процессором по очереди. Потоки в очереди запускается по воли операционной системы. Управляет всеми потоками операционка, кому в какое время запуститься. Но если используется какая-нибудь общая переменная то тут все зависит пряморукости программиста.
 

arshanskiyav

Новичок
Пользователь
Май 17, 2020
3
0
1
Поток ничего не опредиляет - он просто выполняется центральным процессором по очереди. Потоки в очереди запускается по воли операционной системы. Управляет всеми потоками операционка, кому в какое время запуститься. Но если используется какая-нибудь общая переменная то тут все зависит пряморукости программиста.
По коду переменная одна на всех, но ведет себя как 4 разных. Почему так?
 

stud_55

Модератор
Команда форума
Модератор
Апр 3, 2020
1 522
672
113
Собственно вопрос - как поток определяет что сейчас обновилась именно его переменная?
У вас в коде для каждого потока своя очередь. Когда происходит нажатие на кнопку в методе check_button в очередь добавляется true, а в методе blink_led проверяется есть ли что-то в очереди и если есть загораются два светодиода. Номера светодиодов и кнопок поток узнает из аргументов функций, переданных при создании потока.
 
Последнее редактирование:

arshanskiyav

Новичок
Пользователь
Май 17, 2020
3
0
1
У вас в коде для каждого потока своя очередь.
Меня смущает то, что имя что внутри методов, что за их пределами одинаковое.
Я правильно понимаю что это нормальное поведение?
 

stud_55

Модератор
Команда форума
Модератор
Апр 3, 2020
1 522
672
113
Меня смущает то, что имя что внутри методов, что за их пределами одинаковое.
Я правильно понимаю что это нормальное поведение?
Вы можете переименовать аргументы функции, чтобы одинаковые имена не смущали. Или переименовать названия очередей, например:

Python:
runJob1=Queue(1)
ButtonJob_1 = Thread(target=check_button, args=(runJob1,GPIO.PD0,'1',))
LedJob_1 = Thread(target=blink_led, args=(runJob1,GPIO.PD9,GPIO.PD8,'1',))
ButtonJob_1.start()
LedJob_1.start()

runJob2=Queue(1)
ButtonJob_2 = Thread(target=check_button, args=(runJob2,GPIO.PD1,'2',))
LedJob_2 = Thread(target=blink_led, args=(runJob2,GPIO.PD11,GPIO.PD10,'2',))
ButtonJob_2.start()
LedJob_2.start()

runJob3=Queue(1)
ButtonJob_3 = Thread(target=check_button, args=(runJob3,GPIO.PD2,'3',))
LedJob_3 = Thread(target=blink_led, args=(runJob3,GPIO.PD13,GPIO.PD12,'3',))
ButtonJob_3.start()
LedJob_3.start()

runJob4=Queue(1)
ButtonJob_4 = Thread(target=check_button, args=(runJob4,GPIO.PD3,'4',))
LedJob_4 = Thread(target=blink_led, args=(runJob4,GPIO.PD15,GPIO.PD14,'4',))
ButtonJob_4.start()
LedJob_4.start()
 

MaksimD

Пользователь
Пользователь
Май 12, 2020
51
11
8
я не могу понять почему код работает в этом виде, как поток понимает что конкретно сейчас обновилась именно его очередь, если имена одинаковые (runJob):
runJob - этот не переменая, просто аргумент который показывает что в данный момент выполняется только этот поток из очереди
 

Форум IT Специалистов