(Python) Передача потока. Объект через функцию? - PullRequest
0 голосов
/ 06 октября 2009

У меня есть функция таймера:

# This is a class that schedules tasks. It will call it's ring() function
# when the timer starts, and call it's running() function when within the
# time limit, and call it's over() function when the time is up.

# This class uses SYSTEM time.

import time, threading
import settings

from object import Object

class Timer(Object, threading.Thread):
    # INIT -------------------------------------------------------------
    # Init vars
    #
    # If autotick is True (default) the timer will run in a seperate
    # process. Other wise it will need to be updated automatically by
    # calling tick()
    def __init__(self, autotick=False):
        # Call inherited __init__ first.
        threading.Thread.__init__(self)
        Object.__init__(self)

        # Now our vars
        self.startTimeString = "" # The time when the timer starts as a string
        self.endTimeString = "" # The time when the timer stops as a string
        self.timeFormat = "" # The string to use as the format for the string       
        self.set = False # The timer starts deactivated
        self.process = autotick # Wether or not to run in a seperate process.
        self.rung = False # Has the timer rang yet?


    # ACTIVATE --------------------------------------------------------------
    # Sets the timer
    def activate(self, startTime, endTime, format):
        # Set the timer.
        self.startTimeString = startTime
        self.endTimeString = endTime
        self.timeFormat = format

        # Conver the strings to time using format
        try:
            self.startTime = time.strptime(startTime, self.timeFormat)
            self.endTime = time.strptime(endTime, self.timeFormat)
        except ValueError:
            # Error
            print ("Error: Cannot convert time according to format")
            return False

        # Try and convert the time to seconds
        try:
            self.startTimeSecs = time.mktime(self.startTime)
            self.endTimeSecs = time.mktime(self.endTime)
        except OverflowError, ValueError:
            # Error
            print ("Error: Cannot convert time to seconds")
            return False

        # The timer is now set
        self.set = True

        # If self.process is true, we need to start calling tick in a
        # seperate process.
        if self.process:
            self.deamon = True # We don't want python to hang if a timer
                                # is still running at exit.
            self.start()

    # RING -------------------------------------------------------------
    # This function is called when the timer starts.
    def ring(self):
        pass

    # RUNNING ----------------------------------------------------------
    # Called when the the time is whithin the time limits.
    def running(self):
        pass

    # OVER -------------------------------------------------------------
    # Called when the time is up
    def over(self):
        pass

    # TICK -------------------------------------------------------------
    # Call this every loop (or in a seperate process)
    def tick(self): 
        print time.time(), self.startTimeSecs, self.endTimeSecs, time.strftime("%A %H:%M", time.localtime(self.startTimeSecs))

        # Check the time
        if time.mktime(time.localtime()) > self.startTimeSecs and time.mktime(time.localtime()) < self.endTimeSecs and not self.rung:
            # The time has come =)
            # Call ring()
            self.ring()

            # Now set self.rung to True
            self.rung = True

        # If the time is up..
        elif time.mktime(time.localtime()) > self.endTimeSecs and self.rung:
            self.over()

            # Unset the timer
            self.set = False
            self.rung = False

        # If we are inbetween the starttime and endtime.
        elif time.mktime(time.localtime()) > self.startTimeSecs and time.mktime(time.localtime()) < self.endTimeSecs and self.rung:
            self.running()

        # If any of those aren't true, then the timer hasn't started yet
        else:
            # Check if the endTime has already passed
            if time.mktime(time.localtime()) > self.endTimeSecs:

                # The time has already passed.
                self.set = False


    # THREADING STUFF --------------------------------------------------
    # This is run by Threads start() method.
    def run(self):
        while self.set == True:
            # Tick
            self.tick()

            # Sleep for a bit to save CPU
            time.sleep(settings.TIMER_SLEEP)

И я добавляю блоки расписания в планировщик:

# LOAD -------------------------------------------------------------
# Loads schedule from a file (schedule_settings.py).
def load(self):
    # Add blocks
    for block in schedule_settings.BLOCKS:
        # Calculate the day
        start_day = str(getDate(block[1].split()[0]))
        end_day = str(getDate(block[2].split()[0]))

        self.scheduler.add(start_day + " " + block[1].split()[1], end_day + " " + block[2].split()[1], "%j %H:%M", block[0])

    for block in self.scheduler.blocks:
        block.timer.tick()

    print len(self.scheduler.blocks)

    # Start the scheduler (if it isn't already)
    if not self.scheduler.running:
        self.scheduler.start()

Функция добавления выглядит следующим образом:

# ADD --------------------------------------------------------------
# Add a scheduled time
# 
# block should be a Block instance, describing what to do at this time.
def add(self, startTime, endTime, format, block):
    # Add this block
    newBlock = block

    # Start a timer for this block
    newBlock.timer = Timer()

    # Figure out the time
    year = time.strftime("%Y")

    # Add the block timer
    newBlock.timer.activate(year + " " + startTime, year + " " + endTime, "%Y " + format)

    # Add this block to the list
    self.blocks.append(newBlock)

    return

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

Моя проблема в том, что блоки полностью запутались после использования функции добавления. Некоторые дублируются, они находятся в неправильном порядке и т. Д. Однако, перед функцией add они полностью в порядке. Если я использую небольшое количество блоков (2 или 3), это, кажется, работает нормально.

Например, если мой schedule_settings.py (настроен на недельный график) выглядит так:

# -*- coding: utf-8 -*-
# This file contains settings for a week's schedule
from block import Block
from series import Series

# MAIN BLOCK (All old episodes)
mainBlock = Block()
mainBlock.picker = 'random'
mainBlock.name = "Main Block"
mainBlock.auto(".")
mainBlock.old_episodes = True

# ONE PIECE
onepieceBlock = Block()
onepieceBlock.picker = 'latest'
onepieceBlock.name = "One Piece"
onepieceBlock.series = [
        Series(auto="One Piece"),
]

# NEWISH STUFF
newishBlock = Block()
newishBlock.picker = 'random'
newishBlock.auto(".")
newishBlock.name = "NewishBlock"
newishBlock.exclude_series = [
        #Series(auto="One Piece"),
        #Series(auto="Nyan Koi!"),
]

# NEW STUFF
newBlock = Block()
newBlock.picker = 'latest'
newBlock.name = "New Stuff"
newBlock.series = [
        Series(auto="Nyan Koi!"),
]

# ACTIVE BLOCKS
BLOCKS = (
        # MONDAY
        (mainBlock, "Monday 08:00", "Monday 22:20"),
        (onepieceBlock, "Monday 22:20", "Monday 22:30"),
        (newishBlock, "Monday 22:30", "Monday 23:00"),

        # TUESDAY
        (mainBlock, "Tuesday 08:00", "Tuesday 18:00"),
        (newBlock, "Tuesday 18:00", "Tuesday 18:30"),
        (newishBlock, "Tuesday 18:30", "Tuesday 22:00"),

        # WEDNESDAY
        (mainBlock, "Wednesday 08:00", "Wednesday 18:00"),
        (newBlock, "Wednesday 18:00", "Wednesday 18:30"),
        (newishBlock, "Wednesday 18:30", "Wednesday 22:00"),

        # THURSDAY
        (mainBlock, "Thursday 08:00", "Thursday 18:00"),
        (newBlock, "Thursday 18:00", "Thursday 18:30"),
        (newishBlock, "Thursday 18:30", "Thursday 22:00"),

        # FRIDAY
        (mainBlock, "Friday 08:00", "Friday 18:00"),
        (newBlock, "Friday 18:00", "Friday 18:30"),

        # WEEKEND
        (newishBlock, "Saturday 08:00", "Saturday 23:00"),

        (newishBlock, "Sunday 08:00", "Sunday 23:00"),

)

Перед добавлением в планировщик, созданный список выглядит нормально, но после добавления, затем распечатывания, я получаю:

1254810368.0 1255071600.0 1255107600.0 Friday 08:00
1254810368.0 1254777600.0 1254778200.0 Monday 22:20
1254810368.0 1255244400.0 1255298400.0 Sunday 08:00
1254810368.0 1255071600.0 1255107600.0 Friday 08:00
1254810368.0 1255107600.0 1255109400.0 Friday 18:00
1254810368.0 1255244400.0 1255298400.0 Sunday 08:00
1254810368.0 1255071600.0 1255107600.0 Friday 08:00
1254810368.0 1255107600.0 1255109400.0 Friday 18:00
1254810368.0 1255244400.0 1255298400.0 Sunday 08:00
1254810368.0 1255071600.0 1255107600.0 Friday 08:00
1254810368.0 1255107600.0 1255109400.0 Friday 18:00
1254810368.0 1255244400.0 1255298400.0 Sunday 08:00
1254810368.0 1255071600.0 1255107600.0 Friday 08:00
1254810368.0 1255107600.0 1255109400.0 Friday 18:00
1254810368.0 1255244400.0 1255298400.0 Sunday 08:00
1254810368.0 1255244400.0 1255298400.0 Sunday 08:00

Я предполагаю, что это как-то связано с подклассами потоков. Вот что я сделал в своем классе Timer. Это как-то передается через функцию и добавляет ее в список?

(Edit) Извините, если это было не очень кратко, я спешил и забыл опубликовать самый важный код = (Использование таймера для отметки вручную было просто отладочным кодом, обычно у меня было бы auto = True в класс таймера.

Вы можете найти весь мой код по адресу: http://github.com/bombpersons/MYOT

Ответы [ 2 ]

1 голос
/ 06 октября 2009

Вы показываете нам тонны кода, но не ключевые части - часть Планировщика (и что это за особый класс Object в верхнем регистре ...?). В любом случае, ответить на ваш вопрос, передавая экземпляры подклассов Thread через функции, добавляя их в списки и т. Д., Совершенно нормально (хотя другие вещи, которые вы делаете, могут и не быть - например, вы можете не осознавать этого, просто потому что tick является методом подкласса Thread, вызов его из другого потока НЕ ​​означает, что он будет выполняться в своем собственном потоке ... скорее, при вызове он будет выполняться в вызывающем потоке).

Могу ли я предложить использовать модуль sched в стандартной библиотеке Python для реализации функций планирования вместо того, чтобы запускать свои собственные ...?

0 голосов
/ 06 октября 2009

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

Я создал класс schedulerBlock, содержащий таймер и блок. Теперь работает отлично =)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...