Attempting to run a Python script on boot on Raspberry Pi 3B+ 1GB RAM, Raspbian, with a SunFounder 10" Touch Screen, - .log file returns "Bad display name'
Python script is 100% functional when run via Terminal / executable script / Thonny etc. Attempted to run at boot first via rc.local - created a service, enabled service, daemon-reload... etc. Did not work.
Tried to run as crontab, same result - .log output from crontab shows "Bad display name". Thought it was lack of Display Environment imported and declared within the Python script, so I added that - but on boot returns the same result.
This is the Python Script I'm using
#!/usr/bin/env python3
import RPi.GPIO as GPIO
import os
import sys
import webbrowser
import time
import subprocess
from pynput import keyboard
from Xlib.display import Display
#GPIO Readout
GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)
#GPIO Header Setup
header = 2
GPIO.setup(header, GPIO.IN)
#Omxplayer Commands
Loop = 'omxplayer -b --loop --no-osd -o hdmi /home/pi/Videos/PlanetEarth.mp4 > /dev/null'
Donation = 'omxplayer -b --no-osd -o hdmi /home/pi/Videos/Cartoon.mp4 > /dev/null'
KillPlayer = 'pkill omxplayer.bin'
KillForm = 'pkill chromium'
#Set Display Environment
new_env = dict(os.environ)
new_env['DISPLAY'] = ':0.0'
#Form Handling Required Below
#If Donation is successful, Stop Looping Video, Open Form in Chromium, Wait 60 seconds, Close Chromium, Restart Loop
def PullDownSuccess():
subprocess.Popen(KillPlayer, env=new_env, shell=True)
time.sleep(2)
webbrowser.open('<url>')
time.sleep(60)
subprocess.Popen(KillForm, env=new_env, shell=True)
time.sleep(2)
subprocess.Popen(Loop, env=new_env, shell=True)
#Inception
subprocess.Popen(Loop, env=new_env, shell=True)
#Terminate Loop with Escape Key or Manually Initiate Donation Success
def on_press(key):
if key == keyboard.Key.ctrl:
PullDownSuccess()
if key == keyboard.Key.esc:
subprocess.Popen(KillPlayer, shell=True)
#Keyboard Listener Module
with keyboard.Listener(
on_press=on_press) as listener:
listener.join()
#Donation Successful Do:
while True:
header_state = GPIO.input(header)
if header_state == GPIO.HIGH:
PullDownSuccess()
I am currently attempting to run this script on Boot via crontab with this line:
#reboot (/bin/sleep 10; /usr/bin/python3 /home/pi/Custom_Scripts/<script>.py > /home/pi/Custom_Scripts/cronjoblog 2>&1)
The error log file for crontab returns the following:
raise error.DisplayNameError(display)
Xlib.error.DisplayNameError: Bad display name ""
This error only exists when attempting to run script on boot up. Is the Display overriding the boot display permissions on Boot Up? What is keeping the script from running on the Display on boot up, but not when remotely executed? Thank you for your consideration.
Update: Still no solution. Display environment returns ":0.0' ... so far I have tried to remove
> /dev/null from #Omxplayer Commands
Replacing crontab startup line to:
DISPLAY=":0" /usr/bin/python3 /home/pi/Custom_Scripts/<script>.py
and
DISPLAY=":0.0" /usr/bin/python3 /home/pi/Custom_Scripts/<script>.py
And any possible combination of these.
Confirmed the script is not waiting for any background processes as I have added delay (time.sleep) up to 30 seconds, as well as returning IP addresses, etc.
Returns either Bad Display Name still OR "Can't connect to display ":0": b'Invalid MIT-MAGIC-COOKIE-1 key"
Still looking for a solution if anyone has one.
EDIT:
Fixed using /LXDE-pi/autostart. Answer below.
Try to add DISPLAY environment variable before calling your script:
DISPLAY=":0" /usr/bin/python3 /home/pi/Custom_Scripts/<script>.py
DISPLAY="/dev/null" /usr/bin/python3 /home/pi/Custom_Scripts/<script>.py
Have you tried a longer sleep?
If you try to get your ip adress during your startup script with (for example) :
import socket
def get_ip_address():
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.connect(("8.8.8.8", 80))
return s.getsockname()[0]
you will get an errror like:
File "/usr/lib/python2.7/socket.py", line 228, in meth
return getattr(self._sock,name)(*args)
error: [Errno 101] Network is unreachable
This is because at reboot network is not necessarily available. In order to make it available
see https://raspberrypi.stackexchange.com/questions/45769/how-to-wait-for-networking-on-login-after-reboot :
sudo raspi-config
then select option 3 Boot Options
then select option 4 Wait for network at boot
Once you have done that networking should not be an issue at reboot.
You get also check for other ways to enforce network setup before running your script take a look at :
https://askubuntu.com/questions/3299/how-to-run-cron-job-when-network-is-up
If there are unforeseen ramifications for using this method, I will update this thread accordingly. I fixed this issue just by adding two lines to the autostart file which resides in /etc/sdg/lxsession/LXDE-pi/autostart.
sudo nano /etc/xgd/lxsession/LXDE-pi/autostart
Add these two lines, do not modify the existing code.
sleep 5
#/usr/bin/python3 /home/pi/Custom_Scripts/<script>.py
My autostart file looks like this:
#lxpanel --profile LXDE-pi
#pcmanfm --desktop --profile LXDE-pi
#xscreensaver -no-splash
point-rpi
sleep 5
#usr/bin/python3 /home/pi/Custom_Scripts/<script>/py
Ctrl + O to write file
sudo reboot
Related
I need to login to IBM i System using Python without entering the username and password manually.
I used py3270 library but it is not able to detect the Emulator wc3270. The emulator I use has .hod extension and opens with IBM i Launcher.
Can anyone help me with this? what could be the possible solution for this?
os.system() is a blocking statement. That is, it blocks, or stops further Python code from being executed until whatever os.system() is doing has completed. This problem needs us to spawn a separate thread, so that the Windows process executing the ACS software runs at the same time the rest of the Python code runs. subprocess is one Python library that can handle this.
Here is some code that opens an ACS 5250 terminal window and pushes the user and password onto that window. There's no error checking, and there are some setup details that my system assumes about ACS which your system may not.
# the various print() statements are for looking behind the scenes
import sys
import time
import subprocess
from pywinauto.application import Application
import pywinauto.keyboard as keyboard
userid = sys.argv[1]
password = sys.argv[2]
print("Starting ACS")
cmd = r"C:\Users\Public\IBM\ClientSolutions\Start_Programs\Windows_x86-64\acslaunch_win-64.exe"
system = r'/system="your system name or IP goes here"'
# Popen requires the command to be separate from each of the parameters, so an array
result = subprocess.Popen([cmd, r"/plugin=5250",system], shell=True)
print(result)
# wait at least long enough for Windows to get past the splash screen
print("ACS starting - pausing")
time.sleep(5)
print("connecting to Windows process")
ACS = Application().connect(path=cmd)
print(ACS)
# debugging
windows = ACS.windows()
print(windows)
dialog = ACS['Signon to IBM i']
print(dialog)
print("sending keystrokes")
keyboard.send_keys(userid)
keyboard.send_keys("{TAB}")
keyboard.send_keys(password)
keyboard.send_keys("{ENTER}")
print('Done.')
Currently, I am facing the same issue. I was able to run the IBMi (ACS), however, once it run, my python script stop functioning as if the app is preventing the python from being running. In generally speaking, the app seems to not detecting the script.But once I closed the app, my python script continue to work.. I put some indication e.g timesleep, however as i mentioned earlier, it only continue to that line of code once IBM is closed. There will be few lines to be added to move the selection to 5250 and inject the credential.
*I tried with pyautogui, still facing the same issue. so now i tried pywinauto import keyboard .
#Variables
dir = sys.argv[1]
username = sys.argv[2]
password = sys.argv[3]
x = dir.split("\\")
print(x[-1])
command = "cd \ && cd Users/Public/Desktop && " + '"' + x[-1] + '"'
print(command)
os.system(command)
------ FROM THIS LINE OF CODE ONWARDS, IT STOPPED RUNNING ONCE IBM IS LAUNCHED ---
print('TIME START')
time.sleep(5)
print('TIME END')
keyboard.send_keys(username)
keyboard.send_keys(password)
keyboard.send_keys("{ENTER}")
print('Done.')
Appreciate your help to look into this matter. Thanks
Using my odoo.sh project (v13.0.2) > EDITOR-Tab , which redirects me to mywebsite.odoo.com/odoo-sh/editor/lab, when i want to debug using import pdb; pdb.set_trace(), it raises a BdbQuit Error :
File "/usr/lib/python3.6/bdb.py", line 113, in
dispatch_exception
if self.quitting: raise BdbQuit
In the past versions : v13.0.1.xxx, i could use pdb.set_trace() to debug my python code. How to solve this issue ?
rpdb is a remote debugger based on pdb. It re-routes stdin and stdout to a socket handler, so that you can debug server processes (remotely).
In Odoo.sh > yourstagingBranch, click on the SHELL-tab:
mywebsite-oerp-staging-5070461 [staging/v13.0]:~$ pip3 install rpdb
In Odoo.sh > yourstagingBranch, click on the EDITOR-tab:
IN ODOO-EDITOR:
At the top of your python file, add:
import rpdb
In the function (def subscribe) to be inspected, add:
def subscribe(self, event, **post):
# code before
rpdb.set_trace()
# code after
Click on menu Tab : Odoo>Update current module : alternatively, open a new Terminal window and execute this command: odoo-bin -u website_sale --stop-after-init
mywebsite-oerp-staging-5070461 [staging/v13.0]: odoo-bin -u website_sale --stop-after-init
After having restarted Odoo (all modules loaded), execute this command in the other Terminal window: nc 127.0.0.1 4444
mywebsite-oerp-staging-5070461 [staging/v13.0]: ~$ nc 127.0.0.1 4444
We can then use the common pdb commands:
l(ist): Lists the lines surrounding the current line
w(here): Displays the file and line number where we currently are
s(tep): Step into the function at the current line
n(ext): Continue execution until the next line in the current function is reached or it returns. (The difference between next and step is that step stops inside a called function, while next executes called functions at (nearly) full speed, only stopping at the next line in the current function.)
a(rgs): Print the argument list of the current function
p(rint) variablename : Print value of variablename
quit : To quit rPdb
More info : https://itnext.io/debugging-your-code-in-python-pdb-vs-rpdb-e7bb918a8ac3
Official documentation (commands) : https://docs.python.org/3/library/pdb.html
#######
OR, alternatively : Using this post How to debug python CLI that takes stdin? :
in Odoo.sh>EDITOR (Jupyter Lab): Open a first Terminal and create these two fifos which will be used as stdin/stdout to use pdb :
mkfifo fifo_stdin
mkfifo fifo_stdout
cat fifo_stdout & cat > fifo_stdin
...which makes appear a prompt cursor. Keep this Terminal Tab opened.
Write these 2 lines at the top of the Python script to be debugged :
import pdb
mypdb=pdb.Pdb(stdin=open('fifo_stdin','r'), stdout=open('fifo_stdout','w'))
In this Python script, call set_trace() on your customized mypdb:
def _get_total_amount(self):
total_amount = sum(self._get_base_order_lines(program).mapped('price_total'))
mypdb.set_trace()
return total_amount
...
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.
this is my first post to stackoverflow, so please bear with me :)
I'm trying to read the output of iwconfig from a python script to determine whether there is a wifi connection. When I run script (via a bash script that first sets the directory) using crontab #reboot (user, not root), subprocess.check_output(['iwconfig']) always throws an [Errno 2]. This is even true when I catch the error using try/except and loop the code, so it is still running when the Wifi is certainly connected (as I can check with running iwconfig manually). When I run the python script from the command line via the same bash script, it works fine. What am I overlooking?
#!/usr/bin/python3
import subprocess
import time
import logging
logging.basicConfig(filename='wifi_check.log', filemode='w', format='%(name)s - %(levelname)s
- %(message)s', level=logging.DEBUG)
logging.info("Checking for Wifi")
for i in range(20):
try:
iwconfig_output = subprocess.check_output(['iwconfig']).decode('utf-8')
except Exception as err:
logging.error(str(i) + str(err))
else:
logging.debug(str(i) + iwconfig_output)
if "ESSID" in iwconfig_output:
logging.info(str(i) + "Wifi active")
time.sleep(10)
Errno 2 can indicate that the file is not found.
Perhaps iwconfig is not in PATH for the user who executes the script. Try using /sbin/iwconfig (the full path) of the executable to rule this out.
Summary: I am ssh'ing to a remote server and executing a fork1.py script over there which is shown below. But the trouble is that I want the processes to execute in the background, so that I can start multiple services.
I know we can use nohup, etc. but they are not working. Even when I use a & at the end, the process starts, but gets killed when the script terminates.
Here is the code:
import os
import sys
import commands
from var import key_loc
import subprocess
import pipes
import shlex
def check(status):
if status != 0:
print 'Error! '
quit()
else:
print 'Success :) '
file1=open('/home/modiuser/status.txt','a')
file1.write("Success :)\n")
if(sys.argv[1]=="ES"):
os.chdir('/home/modiuser/elasticsearch-0.90.0/bin/')
proc1=subprocess.Popen(shlex.split("nohup ./elasticsearch -p /home/modiuser/es.pid"))
if(sys.argv[1]=="REDIS"):
os.chdir('/home/modiuser/redis-2.6.13/src')
proc2=subprocess.Popen(shlex.split("./redis_ss -p /home/modiuser/redis.pid"))
if(sys.argv[1]=="PARSER"):
proc3=subprocess.Popen(shlex.split("nohup java -jar logstash-1.1.12-flatjar.jar agent -f parser.conf"))
file1=open('/home/modiuser/pid.txt','a')
file1.write("PARSER-"+str(proc3.pid)+"\n")
file1.write(str(proc3.poll()))
file1.close()
if(sys.argv[1]=="SHIPPER_TCP"):
proc4=subprocess.Popen(shlex.split("nohup java -jar logstash-1.1.12-flatjar.jar agent -f shipper_TCP.conf"))
file1=open('/home/modiuser/pid.txt','a')
file1.write("SHIPPER_TCP-"+str(proc4.pid)+"\n")
file1.close()
Where am I going wrong?
just try with
import os
os.system('python program1.py &') #this one runs in the background
os.system('python program2.py') #this one runs in the foreground