在PHP应用程序中启动并控制用Python编写的脚本

时间:2014-03-15 15:10:28

标签: php python inversion-of-control

问题的基础。

我想创建(实际上我差不多完成)应用程序来管理匹配,我​​需要做简单的计时器。应用程序是用PHP创建的。我得到了所有的优点和缺点,我决定用Python创建这个计时器并在服务器上运行..但我不熟悉Python,但是:)

基本概念是将PHP中的Web服务用于:

  • 以传递的值(以秒为单位)启动计时器并匹配id。 Web服务启动Python脚本并获取进程ID。
  • 从运行程序中获取当前计时器值的简单函数
  • 暂停/停止功能,向已经运行的程序发送命令以获取当前值并终止程序。 该脚本应该及时向Web服务发送请求。

我正在运行Python 3.2.3和PHP 5.x(我使用Laravel)。在开发环境中使用Windows 7,在生产环境中使用Raspbian Whezzy。

我做了什么。

我有超级简单的Python计时器脚本(目前仅在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))

我的PHP网络服务启动计时器

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);
}

问题是:

  • 我的脚本未在后台运行。我找到了一个解决方案,在后台添加&以在后台运行进程,但是对于Windows呢?
  • 如何控制我的计时器?在Windows和Linux环境中。
  • 如何创建函数以返回计时器的当前值并停止计时器?

这样做有更好的概念吗?

1 个答案:

答案 0 :(得分:0)

我已经解决了我的问题。

我还没有找到一个解决方法,如何使用PID或其他东西控制我的计时器,而不是我决定发送消息"使用简单文件进出脚本。

我调用我的计时器而不更改以前的版本。如果我想要停止计时器,我会创建一个带有我的计时器ID(匹配ID)和“停止”的文件。 (例如' 5stop'),比我保存当前计时器 - 实际上我一直这样做,并调用告诉我这个事件的网络服务。当我需要检查当前值时,我会检查另一个文件的值,即我的消息'从我的脚本到PHP应用程序。 到目前为止,我没有用Python调用我的Web服务,但我认为这并不困难。

我也尝试使用PHP pthreads扩展(在评论中向我提出),但没有成功。也许我做错了,但这个线程同步为我工作,我不知道如何检查来自其他设备的当前计时器值。

也许这对某人有帮助所以我把脚本放在下面。

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

我希望它能在整个系统中正常运行。到目前为止,它适用于我的测试。 享受。