Correct way to call Pythonista script from within a Shortcuts workflow?
just run the whole script in the background
I don't think that Pythonista can run in the background.
Apple only authorizes that for music or Bluetooth apps.
7upser last edited by 7upser
You can Start a Shortcut with Pythonista:
import webbrowser vUrl = 'shortcuts://run-shortcut?name=testStartWithUrlScheme&input=10' webbrowser.get('safari').open(vUrl)
Maybe you can split your Shortcut into 2 different Shortcuts.
This should work, if you use Url Scheme on both sides.
(it's not really in the Bachground, as cvp mentioned)
Hi everybody, I could call a Pythonista script from shortcuts using url and safari but it works only if the iPad is awake, is there a way to let it work when the iPad is asleep?
I also tried running a Pythonista script using scheduler but it works only if I stay in the Pythonista app.
What I want to achieve is writing some info into a file every hour
@mikeno I don't know what you want to do while your IPad is asleep but Shortcuts offers automations. Perhaps that could help.
Yes but only everyday, I want to read the value of the barometer sensor every hour, I can get this value with Pythonista. I didn’t find a way to get this information in shortcuts nor in JS (scriptable).
I found also a way to do some tasks every hour in shortcuts but I don’t find a way to get the barometer sensor value.
I found also a way to do some tasks every hour in shortcuts
But you could start a Pythonista script every hour?
Yes, it works but only if the iPad is awake
@mikeno did you try to run an automation at specified time, which runs a Pythonista short script logging the pressure in a file and put your IPad asleep some time before the specified time?
@cvp I’m not sure to understand what you mean, but calling a pythonista script from a shortcuts or an automation requires the iPad to be awake
@mikeno ok, I thought that calling the script from the shortcut did launch Pythonista even if iPad not awake. If you have Pyto, you could test because it runs really in background like a music player
I don’t know PyTo but I will try, thx in any case
@mikeno not Py To but Pyto, I think there is a free test version
I just downloaded it but my trial period already expired because I probably already tried it some times ago and since I don’t know if it works, I don’t want to buy it. If you’ve it, could you try if it runs when iPad is asleep?
@mikeno I'll do it and let it know
@mikeno I have tried a script which prints the time each second and closed my iPad cover during 200 seconds and when I have reopened it, the script was still running
Thx, the question is now if Pyto can read the barometer sensor value, below a short code which runs fine under Pythonista:
from objc_util import ObjCInstance, ObjCClass, ObjCBlock, c_void_p pressure = None def get_pressure(): def handler(_cmd, _data, _error): global pressure pressure = ObjCInstance(_data).pressure() handler_block = ObjCBlock(handler, restype=None, argtypes=[c_void_p, c_void_p, c_void_p]) CMAltimeter = ObjCClass('CMAltimeter') NSOperationQueue = ObjCClass('NSOperationQueue') if not CMAltimeter.isRelativeAltitudeAvailable(): print('This device has no barometer.') return altimeter = CMAltimeter.new() main_q = NSOperationQueue.mainQueue() altimeter.startRelativeAltitudeUpdatesToQueue_withHandler_(main_q, handler_block) try: while pressure is None: pass finally: altimeter.stopRelativeAltitudeUpdates() #print('Updates stopped.') return pressure.floatValue()*10 pressure = get_pressure() print(pressure)
@mikeno I know this code but I'm new in Pyto and surely not (yet?) a specialist in ObjectiveC of Pyto.
I don't not yet know how to define an ObjcBlock in Pyto but I'll try.
But, obviously, I'll need some time
# coding: utf-8 from rubicon.objc import * from ctypes import * def handler(_cmd, _data, _error): print(ObjCInstance(_data)) handler_block = ObjCBlock(handler, None, [c_void_p, c_void_p, c_void_p]) def main(): CMAltimeter = ObjCClass('CMAltimeter') NSOperationQueue = ObjCClass('NSOperationQueue') if not CMAltimeter.isRelativeAltitudeAvailable(): print('This device has no barometer.') return altimeter = CMAltimeter.new() main_q = NSOperationQueue.mainQueue altimeter.startRelativeAltitudeUpdatesToQueue_withHandler_(main_q, handler_block) print('Started altitude updates.') try: while True: pass finally: altimeter.stopRelativeAltitudeUpdates() print('Updates stopped.') if __name__ == '__main__': main()
Traceback (most recent call last): File "iCloud/barometer.py", line 8, in <module> handler_block = ObjCBlock(handler, None, [c_void_p, c_void_p, c_void_p]) File "Pyto.app/Lib/rubicon/objc/api.py", line 1834, in __init__ self.struct = cast(self.pointer, POINTER(ObjCBlockStruct)) File "Pyto.app/site-packages/python3.10/ctypes/__init__.py", line 510, in cast return _cast(obj, obj, typ) ctypes.ArgumentError: argument 1: <class 'TypeError'>: wrong type
Thx for trying, I’ll wait!
JonB last edited by JonB
@cvp I believe in Rubicon, the preferred usage is via type annotations and decorators. Also
ObjCBlockwraps ObjC blocks so they can be called in python, while
Blockwraps python so it is calls me in objc-- so you want plain old Block.
I think the way you'd do it in Rubicon is:
@Block def handler(altitudeData: ObjCInstance, err:NSError) -> None: print(altitudeData)
Or, I think you can skip the annotation on ObjCInstances:
@Block def handler(altitudeData, err:NSError) -> None: print(altitudeData)