Question

The basis of the problem.

I want to create (actually I almost done) application to manage a match and I need to do simple timer. Application is created in PHP. I get all the pros and cons for me and I have decided to create this timer in Python and run it on a server ..but I'm not familiar with Python, yet :)

The basic concept is to have web services in PHP to:

  • start timer with passed value (in seconds) and match id. Web service start Python script and get process ID.
  • simple function to get current timer value from running program
  • pause/stop function, send command to already running program to get current value and kill program. The script should send a request to web service on time out.

I'm running Python 3.2.3 and PHP 5.x (I use Laravel). Working with Windows 7 in development environment and Raspbian Whezzy in production environment.

What I have done.

I have super simple Python timer script (currently only tested on Windows)

import sys, json, time

timer = None
matchId = None
active = 1

try:
    data = json.loads(sys.argv[1])
except:
    print("ERROR")
    sys.exit(1)

timer = data[0]
matchId = data[1]

while timer and active:
    timer -= 1;
    time.sleep(1)

if active:
    # call web service
    print("Time out [ID:" + str(matchId) +"]")
else:
    print("Timer has stopped, current value " + str(timer))

My PHP web service to start timer

public function postRun($time, $matchId){
        $scriptPath = public_path().$this->envSlash.'python'.$this->envSlash.'timer.py';
        $data = array($time, $matchId);
        $attr = escapeshellarg(json_encode($data));
        $cmd = "$this->python $scriptPath $attr &"; 
        exec("$cmd", $output);
        print_r($output);
}

The question is:

  • My script is not running in the background. I found a solution to add & on the end to run process in the background but what with Windows?
  • How can I get control of my timer? In both Windows and Linux environment.
  • How can I create functions to return current value of my timer and stop timer?

Is better concept to do that?

Was it helpful?

Solution

I have solved my problem.

I have not found a solution how to control my timer using PID or something, than I decide to "send a message" to/from my script using simple file.

I call my timer without change to previous version. If I want to stop my timer I create a file with my timer ID (match ID) and 'stop' (eg '5stop'), than I save current timer - actually I do it all the time, and call web service which is telling me about this event. When I need to check current value I will check value of another file, that is my 'message' from my script to PHP app. I did't call my web services from Python so far, but I think this is not difficult.

I also tried do it with PHP pthreads extension (as proposed to me in the comments) but with no success. Maybe I did something wrong but this threads working synchronously for me and I don't know how to check current timer value from another device.

Maybe it will be helpful for someone so I put the script below.

import sys, json, time
import logging, datetime
import os

def saveCurrentTime(time):
    currentTimeFile = open(currentTimeFileName, 'w')
    currentTimeFile.write(str(timer))
    currentTimeFile.close()
    return

def checkActiveStatus():
    if os.path.exists(timerStopFileName):
        return 0
    else:
        return 1

now = datetime.datetime.now()
script_dir = os.path.dirname(__file__)

LOG_FILENAME = 'python/log/' + now.strftime("%Y-%m-%d") + '.log' #server config
#LOG_FILENAME = 'log/' + now.strftime("%Y-%m-%d") + '.log' #local test
logging.basicConfig(filename=LOG_FILENAME,level=logging.DEBUG,)
logging.info(now.strftime("%H:%M:%S") + ' New Timer has been started')

timer = None
matchId = None
active = 1
currentTimeFileName = None
timerStopFileName = None
#timerStatusFileName = None

storageRelativePath = '/../../app/storage/timer/'
#storagePath = os.path.join(script_dir, storageRelativePath)
storagePath = script_dir + storageRelativePath

# active = getTimerStatus(matchId)

try:
    data = json.loads(sys.argv[1])
except:
    logging.exception('Can not retrieve arguments. Script will be terminated.')
    print("ERROR")
    sys.exit(1)

timer = data[0]
matchId = data[1]
logging.info(now.strftime("%H:%M:%S") + ' Created Timer [time: ' + str(timer) + ', match: ' + str(matchId) + ']')

currentTimeFileName = storagePath + str(matchId) + "timer"
timerStopFileName = storagePath + str(matchId) + "stop"
#timerStatusFileName = storagePath + str(matchId) + "status"

while timer and active:
    timer -= 1
    saveCurrentTime(timer)
    active = checkActiveStatus()
    time.sleep(1)


if active:
    print("Time out [ID:" + str(matchId) +"]")
    #call web service
else:
    if os.path.isfile(timerStopFileName):
        os.remove(timerStopFileName)
    elif os.path.isdir(timerStopFileName):
        os.rmdir(timerStopFileName)
    print("Timer has stopped, current value " + str(timer))
    #call web service

I hope it will work properly with the entire system. So far, it works with my tests. Enjoy.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top