使用 PHP 运行 Python 脚本


Run Python script with PHP

我有这个python文件:

light.py:

#!/usr/bin/python
import sys
import smbus
import time
from Adafruit_I2C import Adafruit_I2C

class Luxmeter:
i2c = None
def __init__(self, address=0x39, debug=0, pause=0.8):
    self.i2c = Adafruit_I2C(address)
    self.address = address
    self.pause = pause
    self.debug = debug
    self.gain = 0 # no gain preselected
    self.i2c.write8(0x80, 0x03)     # enable the device

def setGain(self,gain=1):
    """ Set the gain """
    if (gain != self.gain):
        if (gain==1):
            self.i2c.write8(0x81, 0x02)     # set gain = 1X and timing = 402 mSec
            if (self.debug):
                print "Setting low gain"
        else:
            self.i2c.write8(0x81, 0x12)     # set gain = 16X and timing = 402 mSec
            if (self.debug):
                print "Setting high gain"
        self.gain=gain;                     # safe gain for calculation
        time.sleep(self.pause)              # pause for integration (self.pause must be bigger than integration time)

def readWord(self, reg):
    """Reads a word from the I2C device"""
    try:
        wordval = self.i2c.readU16(reg)
        newval = self.i2c.reverseByteOrder(wordval)
        if (self.debug):
            print("I2C: Device 0x%02X returned 0x%04X from reg 0x%02X" % (self.address, wordval & 0xFFFF, reg))
        return newval
    except IOError:
        print("Error accessing 0x%02X: Check your I2C address" % self.address)
        return -1

def readFull(self, reg=0x8C):
    """Reads visible+IR diode from the I2C device"""
    return self.readWord(reg);
def readIR(self, reg=0x8E):
    """Reads IR only diode from the I2C device"""
    return self.readWord(reg);
def getLux(self, gain = 0):
    """Grabs a lux reading either with autoranging (gain=0) or with a specified gain (1, 16)"""
    if (gain == 1 or gain == 16):
        self.setGain(gain) # low/highGain
        ambient = self.readFull()
        IR = self.readIR()
    elif (gain==0): # auto gain
        self.setGain(16) # first try highGain
        ambient = self.readFull()
        if (ambient < 65535):
            IR = self.readIR()
        if (ambient >= 65535 or IR >= 65535): # value(s) exeed(s) datarange
            self.setGain(1) # set lowGain
            ambient = self.readFull()
            IR = self.readIR()
    if (self.gain==1):
       ambient *= 16    # scale 1x to 16x
       IR *= 16         # scale 1x to 16x
    if (float(ambient) != 0):
        ratio = (IR / float(ambient)) # changed to make it run under python 2
    else: ratio = 0
    if (self.debug):
        print "IR Result", IR
        print "Ambient Result", ambient
    if ((ratio >= 0) & (ratio <= 0.52)):
        lux = (0.0315 * ambient) - (0.0593 * ambient * (ratio**1.4))
    elif (ratio <= 0.65):
        lux = (0.0229 * ambient) - (0.0291 * IR)
    elif (ratio <= 0.80):
        lux = (0.0157 * ambient) - (0.018 * IR)
    elif (ratio <= 1.3):
        lux = (0.00338 * ambient) - (0.0026 * IR)
    elif (ratio > 1.3):
        lux = 0
    return lux

oLuxmeter=Luxmeter()
i=0
while True:
    light = oLuxmeter.getLux(1)
    if (light != 0):
        print light
        break
    else:
        i+=1
        if (i == 10):
            print light
            break

现在我想在我的树莓派上用 PHP 运行它

echo system("/var/www/light.py")

但该网站的回应什么都没有。我使用 chmod+x 授予所有文件权限,但它没有改变任何东西。如果我输入

python /var/www/light.py

进入控制台它可以工作。

问题是您正在某个用户下运行 Web 服务器,该用户没有使用您正在使用的smbus功能的权限。

您可以通过运行类似 su www-data /usr/bin/python /var/www/light.py 的东西来测试这一点(当然,详细信息会根据您的设置而有所不同)。如果失败了,你知道这是你的问题。(另外,您将看到回溯,这可能会有所帮助。

以具有尽可能少权限的用户身份运行 Web 服务器是一个好主意,但以比可能更少的权限运行它显然不是:)。

*nix 系统上的大多数权限都由用户/组文件权限控制,因此答案可能是将 Web 服务器用户添加到拥有 smbus 的组中。正如你找到的论坛帖子中所暗示的那样,PHP exec 和 python-smbus,该组通常被命名为 i2c ,所以如果你的 Web 服务器用户被命名为 www-data ,你将运行:

sudo adduser www-data i2c

作为旁注,将来不要忽略调用另一个程序的返回值。如果它返回 1 或除 0 以外的任何内容,则表示程序失败,这就是您没有得到任何有用输出的原因。(超过 0 或不是 0,实际值不是标准化的,尽管 2 通常意味着错误的参数。


同时,你还有第二个问题。

正如system文档所解释的那样,system 不会返回已执行命令的输出。

文档暗示您想查看passthru,但这可能也不是您想要的。就像system一样,passthru将输出转储到您的标准输出而不是返回它;唯一的区别是它转储它未被换行符翻译过滤。

如果要检索输出然后回显它,则此处可能想要的是exec,并带有output参数:

如果存在 output 参数,则指定的数组将填充命令的每一行输出。