Capture and save running process - python

I want to capture "print('Recording GPS Position...')" on the SD card. For now, this is printing on terminal directly I want to capture this runtime process (p_1) from terminal and store on the SD card as it is being executed. How do I do this?
Also in general what is a way to capture and store processes at runtime from terminal and store on the SD card (note I do want to store processes as it is being executed and not after its execution is done).
import sys
import os
import time
import subprocess, shlex
import signal
import serial
import psutil
from subprocess import Popen, PIPE
def recording():
flag = 0
ser = serial.Serial('/dev/ttyACM0', 921600, timeout=1)
ser.flushOutput()
# ROSBAG Recordings (Shell commands that execute the messages on the terminal)
messages = 'rosbag record -o GPS_Position.bag dji_sdk/gps_position', 'rosbag record -o IMU_Data.bag dji_sdk/imu', 'rosbag record -o Attitude.bag dji_sdk/attitude', 'rosbag record -o Velodyne_Packets.bag velodyne_packets', 'rosbag record -o Velodyne_Points.bag velodyne_points', # rosbag record -o Velocity.bag dji_sdk/velocity'
while flag == 0:
try:
args1 = shlex.split(messages[0]) # messages[0] = rosbag record -o GPS_Position.bag dji_sdk/gps_position
#print (args1)
p_1 = subprocess.Popen(args1, stdout=PIPE)
print('Recording GPS Position...')
p_1.stdout.flush()

You'll want to choose a directory for your SD card, and instead of print()ing to the terminal you'll write() to the file you choose.
Here is the documentation: https://docs.python.org/3/tutorial/inputoutput.html
Edit: it's been answered better here https://stackoverflow.com/a/8024254/8240691 but it would still be worth your while to look over the input/output documentation.

Related

Terminate Linux process using Python - ffmpeg to terminate a live stream to Youtube

I'm using Raspberry Pi to live stream to Youtube. I use Python and this is my script.
import time
import os
key = 'YouTube'
loader='ffmpeg -f pulse -1 alsa output.platform-bcm2835 audio.analog-stereo.monitor f xllgrab -framerate 24 -video size 740x480-B etc....' + key)
proc= os.system(loader)
process_id = proc.pid
print('Running'.process_id)
time.sleep (60)
proc.terminate()
import sys
sys.exit("Error message")
The script works. However, when I try and terminate it, it remains streaming even though the script finishes.
I also tried terminating the script process_id. However it doesn't stop the stream.
I use Python subprocess and that has never caused a problem in Linux (well, limited to pytest on GitHub Action to be honest):
import time
import subprocess as sp
import shlex
key = 'YouTube'
# this doesn't look like a valid FFmpeg command. Use the version which
# successfully streamed data
loader='ffmpeg -f pulse -1 alsa output.platform-bcm2835 audio.analog-stereo.monitor f xllgrab -framerate 24 -video size 740x480-B etc....' + key)
proc= sp.Popen(shlex.split(loader))
print(f'Running{proc.pid}')
time.sleep (60)
proc.terminate() # or proc.kill()
import sys
sys.exit("Error message")
If it is pulse or x11grab device refusing to terminate, you may need to 'kill' it instead.

Use Raspberry Pi 4B Terminal Command in Python Application

I am currently working on a small Python Application which turns a Raspberry Pi 4B into a 48 Channel Audio-Recorder. Basics work, but during Recording, I need a log file which tells me when recording started, which ALSA warnings occurred and when recording stopped.
The recorder can be started with this terminal command:
pi#raspberrypi:~ $ rec -q -t caf --endian little --buffer 96000 -c 48 -b 24 /home/pi/myssd-one/Aufnahmen/test.caf 2>&1 | tee /home/pi/myssd-one/Aufnahmen/logging.log
this records audio in the test.caf file and writes ALSA warnings to logging.log
So far so good.
The Python Program (which should run on a touchscreen with GUI so recording can easily started and stopped) takes care of variable audio-filenames (date-time-stamp) and controls an LED to show that recording is running.
This part of the code takes care of switching on and off:
#!/usr/bin/env python
from tkinter import *
import shlex
import os
import subprocess
import tkinter.font
import datetime
from gpiozero import LED
import RPi.GPIO as GPIO
GPIO.setmode(GPIO.BCM)
GPIO.setup(11, GPIO.OUT)
def ledToggle():
if led.is_lit:
led.off()
my_env = os.environ.copy()
my_env['AUDIODRIVER'] = 'alsa'
my_env['AUDIODEV'] = 'hw:KTUSB,0'
ledButton["text"] = "Turn Recorder on"
print ("recorder stops")
subprocess.Popen(['sudo', 'pkill', '-SIGINT', 'rec'], env = my_env, shell = FALSE, stdout=subprocess.PIPE)
else:
led.on()
my_env = os.environ.copy()
my_env['AUDIODRIVER'] = 'alsa'
my_env['AUDIODEV'] = 'hw:KTUSB,0'
ledButton["text"] = "Turn Recorder off"
print ("recorder starts")
##reference statement command line: "rec -q -t caf --endian little --buffer 96000 -c 48 -b 24 /home/pi/myssd-one/Aufnahmen/test.caf 2>&1 | tee /home/pi/myssd-one/Aufnahmen/logging.log"
command_line = shlex.split("rec '-q' '-t' 'caf' '--buffer' '96000' '-c 48' '-b 24' '/home/pi/myssd-one/Aufnahmen/test.caf' '"2>&1 | tee"' '/home/pi/myssd-one/Aufnahmen/logging.log'")
p1 = subprocess.Popen(command_line, env = my_env, shell = False, stdout=subprocess.PIPE)
I am trying to move the original command line statement into the subprocess.Popen command, to no success yet. The part where routing to the log file is done, fails. It looks as the initiating sox-application 'rec' tries to interpret it as part of its own parameter list, instead of interpreting it as a redirection of stdout and stderr to the log file. I appreciate some guidance in this issue.
Variable Filenames for audio files is already done, but for simplicity taken out of this code snippet.
Thanks Mark, I dived into this command line along your hint that it only can run with shell=True and this implied that it had to be written as a full statement without separating commas and escape quotes. Now it works. Actually, the shlex.split() becomes obsolete.

Run cmd file using python

I have a cmd file "file.cmd" containing 100s of lines of command.
Example
pandoc --extract-media -f docx -t gfm "sample1.docx" -o "sample1.md"
pandoc --extract-media -f docx -t gfm "sample2.docx" -o "sample2.md"
pandoc --extract-media -f docx -t gfm "sample3.docx" -o "sample3.md"
I am trying to run these commands using a script so that I don't have to go to a file and click on it.
This is my code, and it results in no output:
file1 = open('example.cmd', 'r')
Lines = file1.readlines()
# print(Lines)
for i in Lines:
print(i)
os.system(i)
You don't need to read the cmd file line by line. you can simply try the following:
import os
os.system('myfile.cmd')
or using the subprocess module:
import subprocess
p = subprocess.Popen(['myfile.cmd'], shell = True, close_fds = True)
stdout, stderr = proc.communicate()
Example:
myfile.cmd:
#ECHO OFF
ECHO Grettings From Python!
PAUSE
script.py:
import os
os.system('myfile.cmd')
The cmd will open with:
Greetings From Python!
Press any key to continue ...
You can debug the issue by knowing the return exit code by:
import os
return_code=os.system('myfile.cmd')
assert return_code == 0 #asserts that the return code is 0 indicating success!
Note: os.system works by calling system() in C can only take up to 65533 arguments after a command (so it is a 16 bit issue). Giving one more argument will result in the return code 32512 (which implies the exit code 127).
The subprocess module provides more powerful facilities for spawning new processes and retrieving their results; using that module is preferable to using this function (os.system('command')).
since it is a command file (cmd), and only the shell can run it, then shell argument must set to be true. since you are setting the shell argument to true, the command needs to be string form and not a list.
use the Popen method for spawn a new process and the communicte for waiting on that process (you can time it out as well). if you whish to communicate with the child process, provide the PIPES (see mu example, but you dont have to!)
the code below for python 3.3 and beyond
import subprocess
try:
proc=subprocess.Popen('myfile.cmd', shell=True, stderr=subprocess.PIPE, stdout=subprocess.PIPE)
outs, errs = proc.communicate(timeout=15) #timing out the execution, just if you want, you dont have to!
except TimeoutExpired:
proc.kill()
outs, errs = proc.communicate()
for older python versions
proc = subprocess.Popen('myfile.cmd', shell=True)
t=10
while proc.poll() is None and t >= 0:
print('Still waiting')
time.sleep(1)
t -= 1
proc.kill()
In both cases (python versions) if you dont need the timeout feature and you dont need to interact with the child process, then just, use:
proc = subprocess.Popen('myfile.cmd', shell=True)
proc.communicate()

Kill python script launched by a subprocess called by another script (Windows)

I'm trying to integrate ESA'2 sen2cor python-script into my workflow. To do this I create a subprocess with which I call the "L2A_Process.bat" file, which in turn calls the "L2A_Process.py" script.
I want to launch the sen2cor-script with a timeout since it gets stuck and freezes from time to time, so as to automatically re-launch it if it failed.
To launch it and catch a timeout I successfully used the following script:
import os, subprocess
from signal import CTRL_BREAK_EVENT
timeout = 3600 #1hour
l1c_safe_path = "path/to/my/input/file.SAFE" #product that I want to process
command = ["L2A_process.bat", l1c_safe_path]
p = subprocess.Popen(command,shell=False, creationflags=subprocess.CREATE_NEW_PROCESS_GROUP)
try:
p.wait(timeout)
except subprocess.TimeoutExpired:
os.kill(p.pid, CTRL_BREAK_EVENT)
This is as far as I got. It results in the sen2cor-script being paused giving the following output:
Terminate batch job (Y/N)
I'd like to know how I can properly terminate my subprocess "p" with all it own child-subprocesses (i.e. "L2A_Process.py").
Some observations:
This script needs to run on Windows;
I've tried to kill the subprocess without the creationflag I've used in the example above: this results in the subprocess being killed but the "L2A_Process.py" script deteaches an keeps running (which is the core of my problem);
I cannot use a CTRL_C_EVENT since I want to re-launch the failed "L2A_Process.py" in a loop until it succeeds.
This code works for me to monitor Sen2cor status while converting L1C to L2A for Sentinel 2 data. The Sen2cor process is time and cpu consuming so be patient. It took half an hour to create L2A with DEM, DDV, etc. Hope it helps
from subprocess import Popen, PIPE
import os
pathtoprodS1C = "path_to_L1C_product" // safe file
outdirS2A = "output_dir" // where L2A files will be placed
pathtoL2Process = "path_to_L2A_Process" //if not in path
pathtoGIPP = "path_to_your_GIPP/L2A_GIPP.xml"
procName = "./L2A_Process"
os.chdir(pathtoL2Process)
import shlex
pcall = "./{} {} --output_dir {} --tif --GIP_L2A {}".format(procName,
pathtoprodS1C,
pathtoprodS2A,
pathtoGIPP)
args = shlex.split(pcall)
print(args)
try:
p = Popen(args, stdout=PIPE)
eut = p.stdout.readline()
while eut:
eut = p.stdout.readline()
print(eut)
finally:
print('Sen2Cor is Done')
exit()

Checking process status from Python

I am running on a Linux x86-64 system. From a Python (2.6) script, I wish to periodically check whether a given process (identified by pid) has become "defunct"/zombie (this means that entry in the process table exists but the process is doing nothing). It would be also good to know how much CPU the process is consuming (similar to what 'top' command shows).
Can somebody give me some pointers on how I can get these in Python?
I'd use the psutil library:
import psutil
proc = psutil.Process(pid)
if proc.status() == psutil.STATUS_ZOMBIE:
# Zombie process!
you can get top result in python as below:
linux:
import sys, os
f = os.popen("top -p 1 -n 1", "r")
text = f.read()
print text
update
windows:
from os import popen
from sys import stdin
ps = popen("C:/WINDOWS/system32/tasklist.exe","r")
pp = ps.readlines()
ps.close()
# wow, look at the robust parser!
pp.pop(0) # blank line
ph = pp.pop(0) # header line
pp.pop(0) # ===
print ("%d processes reported." % len(pp))
print ("First process in list:")
print (pp[0])
stdin.readline()

Categories

Resources