Python脚本使用子进程来获取PID并杀死它,当从其所在目录外启动时,它的行为很奇怪

2024-04-23 11:58:15 发布

您现在位置:Python中文网/ 问答频道 /正文

提前感谢您抽出时间来阅读这个问题。我正在学习Python,在问这个问题之前我查了很多,请原谅我的新手问题

因此,我在python3中创建了这个脚本,使用subprocess模块搜索另一个python脚本的PID,同时只知道脚本名称的开头并很好地终止它

基本上,我通过Raspberry和I2C在LCD屏幕上运行python时钟,然后终止脚本,清除LCD并将其关闭。下面提供了这个“关闭”脚本代码

问题是,当我从它所在的目录运行它时,它带有:

python3 off.py

它工作得很好,解析并终止PID,然后关闭LCD显示

理想情况下,我希望通过telegramcli触发它,因为我在bash中完成了它,它工作得很好,我发现它是一个很好的特性。在python中它失败了

所以我测试了一下,当我试着从另一个目录启动它时,像这样:

python3 ~/code/off.py

grep子进程返回的PID多于从脚本驻留目录启动时通常返回的PID。例如(使用python3-v):

kill: failed to parse argument: '25977
26044'

第二个PID编号来自脚本创建的子进程,我似乎找不到它是什么,因为它在脚本结束时终止,但没有达到最初的目的

如果您能帮助我们了解这里发生的一切,我们将不胜感激。 到目前为止,正如下面所示,我从两行难看的bash混合调用到一个虚拟的四行python脚本,所以我真的觉得我正在接近实现我的第一个真正python脚本的正确方法

我试图在解释器中逐行分解脚本,但无法再现错误,一切都按预期进行。我只在从外部位置运行脚本时得到这个双PID结果

提前感谢您对如何理解正在发生的事情的任何有用的见解

#!/usr/bin/env python3

import subprocess
import I2C_LCD_driver
import string

# Defining variables for searched strings and string encoding
searched_process_name = 'lcd_'
cut_grep_out_of_results = 'grep'
result_string_encoding = 'utf-8'
mylcd = I2C_LCD_driver.lcd()
LCD_NOBACKLIGHT = 0x00
run = True

def kill_script():
    # Listing processes and getting the searched process
    ps_process = subprocess.Popen(["ps", "aux"], stdout=subprocess.PIPE)
    grep_process = subprocess.Popen(["grep", "-i", searched_process_name], stdin=ps_process.stdout, stdout=subprocess.PIPE)
    # The .stdout.close() lines below allow the previous process to receive a SIGPIPE if the next process exits.
    ps_process.stdout.close()
    # Cleaning the result until only the PID number is returned in a string
    grep_cutout = subprocess.Popen(["grep", "-v", cut_grep_out_of_results], stdin=grep_process.stdout, stdout=subprocess.PIPE)
    grep_process.stdout.close()
    awk = subprocess.Popen(["cut", "-c", "10-14"], stdin=grep_cutout.stdout, stdout=subprocess.PIPE)
    grep_cutout.stdout.close()
    output = awk.communicate()[0]
    clean_output = output.decode(result_string_encoding)
    clean_output_no_new_line = clean_output.rstrip()
    clean_output_no_quote = clean_output_no_new_line.replace("'", '')
    PID = clean_output_no_quote
    # Terminating the LCD script process
    subprocess.Popen(["kill", "-9", PID])

while run:
    kill_script()
    # Cleaning and shutting off LCD screen
    mylcd.lcd_clear()
    mylcd.lcd_device.write_cmd(LCD_NOBACKLIGHT)
    break

Tags: the脚本cleanoutputstringlcdstdoutprocess
1条回答
网友
1楼 · 发布于 2024-04-23 11:58:15

我发现了这种奇怪行为的原因。我这边有个错误: 我忘了我用一个名字调用了一些目录,其中包括我运行grep-I时的字符串,以防止在目录外使用其完整路径运行脚本时产生双重结果。 结果表明,使用子进程可以很好地运行脚本

所以最后,我重命名了我想用disp而不是lcd终止的脚本,并在我的子进程中添加了shell=False,以确保在运行脚本时不会有不小心将输出发送到bash的风险

相关问题 更多 >