Python script runs fine from terminal but crashes when run from crontab - python

I have a simple python script that takes screenshots of a computer that is running Ubuntu. I want it to run automatically on startup, so I put #reboot python3 /bin/program.py in the non-sudo version of crontab.
The program works fine when run from terminal, but gives the error pyscreenshot.err.FailedBackendError. I put it in a try loop, and had it write all exceptions to a file, and that's how I found the error message, "All backends failed."
It has something to do with the program 'pyscreenshot' not working correctly.
import pyscreenshot as screen
import os
from numpy import random
from time import sleep
from os.path import expanduser
TMP_SCREEN_PATH = expanduser('~') + '/.UE/tmp.png'
LOG_FILE_PATH = expanduser('~') + '/.UE/log.txt'
GRAB_DELAY_RANGE = (1, 10)
def screenshot(save_path=TMP_SCREEN_PATH):
img = screen.grab()
img.save(save_path)
def delay(delay_range):
sleep_time = random.randint(delay_range[0], delay_range[1])
print(f"Sleeping for {sleep_time} seconds")
sleep(sleep_time)
def main():
try:
while True:
screenshot()
delay(GRAB_DELAY_RANGE)
except KeyboardInterrupt:
print("Nope")
main()
except Exception as e:
print(e)
with open(LOG_FILE_PATH, 'a') as f:
f.write(str(type(e))+str(e)+'\n')
sleep(5)
main()
f = open(LOG_FILE_PATH, 'w+')
f.write('Startup')
f.close()
main()
I need one of the following solutions:
Simply fix the problem
Another way to run a program at startup
A different module to take screenshots with
Any help is appreciated, thanks

If the user that the cron job runs as is also logged in on the console (you mention a reboot, so I'm guessing that you have enabled autologin), then your cron job might work if you also add:
os.environ["DISPLAY"] = ":0"
This worked for me on Ubuntu in a test using cron and a simplified version of your script:
import os
import pyscreenshot as screen
os.environ["DISPLAY"] = ":0"
img = screen.grab()
img.save("/tmp/test.png")
If it doesn't work for you, then you might also have to try setting the value of the XAUTHORITY environment variable to the value found in the environment of the user's interactive processes, which could be extracted using the psutil package, but let's hope this isn't needed.

Related

How to login to IBM 5250 emulator using Python/Java/.NET? [duplicate]

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

Python script autorun on windows startup

I am trying to create a script that will display a page in chrome on startup. That is, I am trying to run a python script on startup. I am using the winreg module to do so.
Here is my script to add a my page display script on startup:
import winreg
import os
import sys, traceback
def AddToRegistry():
pth = os.path.dirname(os.path.realpath(path_to_page_display_script))
s_name="test.py"
address=os.path.join(pth,s_name)
try:
open = winreg.OpenKey(winreg.HKEY_CURRENT_USER, r"Software\\Microsoft\\Windows\\CurrentVersion\\Run", reserved=0, access = winreg.KEY_ALL_ACCESS)
winreg.SetValueEx(open,"pytest",0,winreg.REG_SZ,address)
winreg.CloseKey(open)
except Exception:
traceback.print_exc(file=sys.stdout)
if __name__=="__main__":
AddToRegistry()
Here is my page display script:
import webbrowser
url = 'http://docs.python.org/'
chrome_path = 'path_to_chrome/chrome.exe %s'
webbrowser.get(chrome_path).open(url)
The script runs fine without any errors but on restarting my machine, the chrome does not open up by itself nor does it display the page. Basically, my script does not run. What is wrong ? Kindly help me out.
The problem isn't with your script. It's with your registry key.
You need to tell windows to invoke Python.exe C:\path_to_script\test.py, not test.py.
So instead of this:
This:
path_to_python_exe = "C:\\python\\python38";
address=os.path.join(pth,s_name)
address = os.path.join(path_to_python_exe, "python.exe") + " " + address;
Or if Python.exe is guaranteed to be in your PATH, simply this:
address = "Python.exe" + " " + os.path.join(pth,s_name)

Using python how to display dns

Using Python, is there a way using psutil or something else to return the output of "ipconfig /displaydns" or something similar?
Spawning a cmd process and running the command is not an option.
To execute a command, you can use the os library. Executing the command you've shown above is as simple as:
import os
os.system('ipconfig /displaydns')
If you want to store the output of a command in a variable, you can use:
x = os.popen('ipconfig /displaydns')
You can try using dnspython's resolver class, which has a nameservers list attached to it.
import dns.resolver
resolver = dns.resolver.Resolver()
resolver.nameservers
# Returns ['8.8.8.8', '8.8.4.4', '8.8.8.8'] on my pc
This python script I made creates a directory in widows user profile and copies windows dns information into a log.txt,So if directory does not exist it will create it. Hope it works for you.
#!/usr/bin/env python3
import time
import os
def dns():
path = os.system("ipconfig /displaydns >> %USERPROFILE%\DNS\logdns.txt")
if path == False:
os.system("ipconfig /displaydns >> %USERPROFILE%\DNS\logdns.txt")
print("Please wait copying information........")
time.sleep(5 )
os.system("cls")
print("Information copy complete.")
time.sleep(3)
else:
print("Making directory please wait a second....")
time.sleep(5)
os.system("cls")
os.system("mkdir %USERPROFILE%\DNS")
time.sleep(1)
dns()
dns()

Cocoa app cannot start looping python script. Works when built/run through xcode

I'm trying to use NSTask to start a looping python script from a cocoa app. The python script ends up in the app's Contents/Resources folder.
I get the path to the script and create the NSTask with:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSString *scriptPath = [[NSBundle mainBundle] pathForResource:filename ofType:#"py"];
NSTask* task = [[NSTask alloc] init];
task.launchPath = PYTHON_PATH;
task.arguments = [NSArray arrayWithObjects:scriptPath, nil];
[task launch];
[task waitUntilExit];
});
(I've omitted the stdOutPipe stuff for readability)
When I build & run my app from xcode it works as expected, the task holds at waitUntilExit and the python script runs continuously.
When I try to run this from the produced .app file it gets to waitUntilExit, stalls for awhile, and then exits with an error. I have logging in the python script so I know that no part of the script is run during this time. The script path is true to the location of the python scripts and returns the same path when run from xcode or from the .app.
I figure I must have some of the project settings set-up incorrectly, but it seems like its handling resources correctly. Any idea?
Update 1
Running a non-looping python script with just a print statement works for the .app. The followings non-looping script fails as well:
#!/usr/bin/python
import os
def log(string):
print(string)
path = os.environ['PWD'] + '/smoke_screen_test.txt'
f1=open(path, 'a')
f1.write(string + "\n")
if __name__ == '__main__':
log("Test works")
exit(0)
Maybe the import statements mess it up? Or the file creation?
The problem was the use of os.environ['PWD']. PWD does not return the local directory of the script being executed. Duh. Solution is to grab the path of the script from argv[0] and use the directory of that path:
path = os.path.dirname(sys.argv[0])
Then pass path around as needed.

Python - how to run the application and leave until it end?

How can i run the application and leave instead of waiting when it will be ended? for example : /var/tmp/runme.sh &
Following code is working but it waits forever when Google Chrome will exit. how can i run Google Chrome but let my script exit?
import subprocess
import sys
import time
line = sys.argv[1]
print line
def kill_chrome():
subprocess.call(['Taskkill', '/IM', 'chrome.exe', '/F'])
def run_chrome():
subprocess.call(['C:/Program Files (x86)/Google/Chrome/Application/chrome.exe', '--kiosk'])
def run_java():
subprocess.call(['java', '-cp', 'C:/Python27/pdfbox-app-2.0.0-RC3.jar;C:/Python27/jprint.jar', 'JPrint'])
try:
if line.startswith("myjava:website"):
print "Google Chrome - IDLE"
run_chrome()
elif line.startswith("myjava:a4"):
print "Printing - JAVA"
run_java()
elif line.startswith("myjava:kill"):
print "Killer"
kill_chrome()
except Exception, err:
print (err)
pass
#time.sleep(2)
What about subprocess.Popen? Looks like it does exactly what you want - runs app end does not waiting. You also pass arguments to the runned application.
from subprocess import Popen
Popen( [ "C:/Program Files (x86)/Google/Chrome/Application/chrome.exe", "myarg"])
Without "myarg" it works too.

Categories

Resources