【问题标题】:How to stop a script within a script如何在脚本中停止脚本
【发布时间】:2018-06-28 12:22:04
【问题描述】:

我希望使用 X-CTU 通过 Zigbee/XBee 控制脚本。我创建了一个名为zb_control.py 的脚本。现在我试图在这个脚本中启动和停止另一个脚本。脚本adxl345test.py 用于从我的 Raspberry Pi 上连接的加速度计收集数据。

zb_control.py 脚本背后的想法是我运行它,然后如果我在 X-CTU 中键入“run”,脚本将开始运行 adxl345test.py 并收集数据。

我正在尝试在脚本中创建一个脚本,该脚本也可以再次停止,然后仍然让 zb_control.py 运行以准备接收来自 X-CTU 的新输入。

如你所知,我尝试了不同的方法:

import serial, time, sys, os, subprocess
from subprocess import check_call
from subprocess import call

while True:

    ser=serial.Serial('/dev/ttyUSB0',9600,timeout=2)
    inc=ser.readline().strip()

    if inc=='run':
        print("---------------")
        print("Collecting data")
        print("---------------")
        p = subprocess.Popen("/home/pi/adxl345test.py", stdout=subprocess.PIPE, shell=True)

    elif inc=='stop':
        # check_call(["pkill", "-9", "-f", adxl345test.py])
        # serial.write('\x03')
        # os.system("pkill –f adxl345test.py")
        # call(["killall", "adxl345test.py"])
        p.kill()
        print("-----------------------")
        print("Script has been stopped")
        print("-----------------------")

我让它运行,它现在正在正确收集数据。但是现在问题是再次停止 adxl345test.py。从上面的脚本可以看出,我正在使用 p.kill() 但脚本不会停止收集数据。当我在 XCTU 中键入“停止”时,我的 zb_control.py 确实打印了打印命令,但 p.kill() 没有被执行。有什么建议吗?

我试过单独使用p.terminate()p.kill() 以及它们自己的命令,但它不会停止adxl345test.py 脚本。我可以看出 .csv 文件的大小仍在增加,因此脚本必须仍在收集数据。

【问题讨论】:

  • 这可能无法解决您的问题,但首先执行p.terminate() 以便将 SIGTERM 信号发送到进程并允许它通过适当的清理等正常终止可能是有意义的。请注意,收到 SIGTERM 后,进程将需要一些时间才能停止。
  • +1 使用 SIGTERM。以下是如何在 python 中优雅地处理它:stackoverflow.com/questions/18499497/…
  • adxl345test.py 是您编写的脚本还是您在某处找到的东西?如果它是您自己的代码,您可能需要考虑更改它,以便它可以正确停止。通过捕获信号(杀死或终止),或检查某种事件,甚至像检查某个目录中是否存在oh_god_please_stop.txt 文件这样粗略的事情。

标签: python kill terminate


【解决方案1】:

我的建议:

  • 如果您在指定的时间间隔内执行某项操作,最好使用 threading.Timer 而不是自己检查时间。
  • 正如我在评论中所说,您可以检查退出条件,而不是粗暴地终止进程。这也允许正确清理您需要的内容。
  • 那些time1...time6真的不好看,来个清单怎么样?此外,time2, time3, time4, time5, time6 也未使用。
  • 实际上不需要 strftime 来获取小时、日、月、年等。它们已经作为属性存在。

你可以这样做:

cur_time = datetime.datetime.now()
cur_hour = cur_time.hour
cur_minute = cur_time.minute

...等等,这样更好一些。在这种特定情况下,这无关紧要,但是如果您开始测量毫秒,则在几行代码之后时间会略有不同,因此您应该将其存储并从变量中使用。

其余的,如果你要一个例子,这里我检查一个文件是否存在来判断是否停止。它非常粗略,但它应该给你一个起点:

from threading import *
from os.path import exists

def hello():
    print('TEST') # Instead of this, do what you need
    if (exists('stop_file.txt')):
        return
    t = Timer(0.5, hello)
    t.start()

hello()

然后在另一个创建中,当您希望它停止时创建停止文件(不要忘记在再次启动之前添加一行将其删除)。

【讨论】:

    【解决方案2】:

    这里是adxl345test.py 脚本供感兴趣的人使用:

    #!/usr/bin/python
    # -*- coding: utf-8 -*-
    # Example on how to read the ADXL345 accelerometer.
    # Kim H. Rasmussen, 2014
    import sys, math, os, spidev, datetime, ftplib
    
    # Setup SPI
    spi = spidev.SpiDev()
    #spi.mode = 3    <-- Important: Do not do this! Or SPI won't work as intended, or even at all.
    spi.open(0,0)
    spi.mode = 3
    
    # Read the Device ID (should be xe5)
    id = spi.xfer2([128,0])
    print 'Device ID (Should be 0xe5):\n'+str(hex(id[1])) + '\n'
    
    # Read the offsets
    xoffset = spi.xfer2([30 | 128,0])
    yoffset = spi.xfer2([31 | 128,0])
    zoffset = spi.xfer2([32 | 128,0])
    accres = 2
    accrate = 13
    print 'Offsets: '
    print xoffset[1]
    print yoffset[1]
    # print str(zoffset[1]) + "\n\nRead the ADXL345 every half second:"
    
    # Initialize the ADXL345
    def initadxl345():
        # Enter power saving state
        spi.xfer2([45, 0])
        # Set data rate to 100 Hz. 15=3200, 14=1600, 13=800, 12=400, 11=200, 10=100 etc.
        spi.xfer2([44, accrate])
    
        # Enable full range (10 bits resolution) and +/- 16g 4 LSB
        spi.xfer2([49, accres])
    
        # Enable measurement
        spi.xfer2([45, 8])
    
    # Read the ADXL x-y-z axia
    def readadxl345():
        rx = spi.xfer2([242,0,0,0,0,0,0])
    
        #
        out = [rx[1] | (rx[2] << 8),rx[3] | (rx[4] << 8),rx[5] | (rx[6] << 8)]
        # Format x-axis
        if (out[0] & (1<<16 - 1 )):
            out[0] = out[0] - (1<<16)
    #   out[0] = out[0] * 0.004 * 9.82
        # Format y-axis
        if (out[1] & (1<<16 - 1 )):
            out[1] = out[1] - (1<<16)
    #   out[1] = out[1] * 0.004 * 9.82
        # Format z-axis
        if (out[2] & (1<<16 - 1 )):
            out[2] = out[2] - (1<<16)
    #   out[2] = out[2] * 0.004 * 9.82
    
        return out
    
    # Initialize the ADXL345 accelerometer
    initadxl345()
    
    # Read the ADXL345 every half second
    timetosend = 60
    while(1):
        with open('/proc/uptime','r') as f: # get uptime
            uptime_start = float(f.readline().split()[0])
        uptime_last = uptime_start
        active_file_first = "S3-" + str(pow(2,accrate)*25/256) + "hz10bit" + str(accres) + 'g' + str(datetime.datetime.utcnow().strftime('%y%m%d%H%M')) $
        active_file = active_file_first.replace(":", ".")
        wStream = open('/var/log/sensor/' + active_file,'wb')
        finalcount = 0
        print "Creating " + active_file
        while uptime_last < uptime_start + timetosend:
            finalcount += 1
            time1 = str(datetime.datetime.now().strftime('%S.%f'))
            time2 = str(datetime.datetime.now().strftime('%M'))
            time3 = str(datetime.datetime.now().strftime('%H'))
            time4 = str(datetime.datetime.now().strftime('%d'))
            time5 = str(datetime.datetime.now().strftime('%m'))
            time6 = str(datetime.datetime.now().strftime('%Y'))
            axia = readadxl345()
            wStream.write(str(round(float(axia[0])/1024,3))+','+str(round(float(axia[1])/1024,3))+','+str(round(float(axia[2])/1024,3))+','+time1+','+ti$
        # Print the reading
        # print axia[0]
        # print axia[1]
        # print str(axia[2]) + '\n'
        # elapsed = time.clock()
        # current = 0
        # while(current < timeout):
        #   current = time.clock() - elapsed
            with open('/proc/uptime', 'r') as f:
                    uptime_last = float(f.readline().split()[0])
        wStream.close()
    
    def doftp(the_active_file):
        session = ftplib.FTP('192.0.3.6','sensor3','L!ghtSp33d')
        session.cwd("//datalogger//")
        file = open('/var/log/sensor/' + active_file, 'rb')   # file to send
        session.storbinary('STOR' + active_file, file)        # send the file
        file.close()
        session.quit
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-04-11
      • 2019-10-14
      • 1970-01-01
      • 2017-08-05
      • 2020-05-05
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多