Run Python Script at OS X Startup - macos

I am very new to python as well as MAC OSX. For my academic project I need to download a bunch of tweets from twitter using twitter streaming API. I need to download atleast 5000000 tweets. So I have written a python script and placed it in start-up. "System Preference -> Users and Groups -> Login items" and added my script there. But I see that the script is not executed when I login to the system ! Please help me resolve this issue.

Adapt the following accordingly, name it something like myscript_launcher.plist, and put it in either one of three locations: /System/Library/LaunchAgents, /System/Library/LaunchDaemons, /Users/<username>/Library/LaunchAgents.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>my.python.script.name</string>
<key>ProgramArguments</key>
<array>
<string>/path/to/python</string>
<string>/path/to/python/script.py</string>
</array>
<key>StandardErrorPath</key>
<string>/var/log/python_script.error</string>
<key>KeepAlive</key>
<true/>
</dict>
</plist>
Also, let's assume you put the plist file in ~/Library/LaunchAgents. You can start and stop it with the launchctl. To start, use launchctl load ~/Library/LaunchAgents/myscript_launcher.plist. To stop it, do the same but use the unload argument

You need to create a shell file that launches your python code. Tell the shell script to start at log in.
example
#!/bin/bash
python username/Desktop/startupscripts/file.py
save the file with the .sh extension.
add the .sh file to
"System Preference -> Users and Groups -> Login items", the .sh script will call the python file.
This is what you should have in the shell file. I'm assume this is the path to the file, if it isn't modify it.
#!/bin/bash
python /Users/username/moviebuzz-api/flask/bin/streaming_movies.py
nothing else.

Here's the full solution I am using on Mojave:
Plist: ~/Library/LaunchAgents/play.with.mpv.plist
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Disabled</key>
<false/>
<key>EnvironmentVariables</key>
<dict>
<key>PATH</key>
<string>/Users/e/Library/Python/3.7/bin:/usr/local/bin</string>
</dict>
<key>KeepAlive</key>
<true/>
<key>Label</key>
<string>play.with.mpv</string>
<key>ProgramArguments</key>
<array>
<string>/usr/local/bin/python3</string>
<string>/Users/e/Library/Python/3.7/bin/play-with-mpv</string>
</array>
<key>RunAtLoad</key>
<true/>
<key>StandardErrorPath</key>
<string>/tmp/play.with.mpv.stderr</string>
<key>StandardOutPath</key>
<string>/tmp/play.with.mpv.stdout</string>
</dict>
</plist>
Mind the PATH to python3 - find it with which python3 and the play-with-mpv python script!
Load plist:
launchctl load ~/Library/LaunchAgents/play.with.mpv.plist
If your video is dropping frames as hell, create mpv config in ~/.config/mpv/mpv.conf and put there this:
video-sync=display-resample
if that do doesn't help, try this instead
opengl-early-flush=no

But I see that the script is not executed when I login to the system !
The problem is, .py files are usually opened by some text editor by default. In order to execute the script as Login Items, you need to make the script to be opened by Terminal.app (or anything execute the script) by default.
After that, you cat set the script as Login Items in the way you posted.
How to set Terminal.app as default:
Put a #! line on the top of the script:
#!/usr/bin/env python3
print("hello world")
Add execute permission to the script:
chmod u+x script.py
Change the file extension .py to .command (to associate the file with Terminal.app):
mv script.py script.command
At this point, you should be able to run the script by double clicking on Finder.
If you can not, try the following:
Right click on the script file on Finder.
Select Get Info
Click the dropdown of Open with: option.
Select Terminal.app
By the way, the above applies to not only python, but other scripts such as bash.
For example of bash, change !# like so:
#!/usr/bin/env bash

Related

Set metadata field on file

I have a PDF file. If I look at the Get Info window, the Title under More Info is "Title1". I am trying to set this value using terminal so I can eventually turn it into an applescript.
See Stackoverflow question Mac OS X : add a custom meta data field to any file
I used the answer from Anderson Freitas to correctly set an author by using the command"
xattr -wx "com.apple.metadata:kMDItemAuthors" "`xxd -ps author.plist`" "Put File Name Here.pdf"
However, if I replace kMDItemAuthors with mMDItemTitle, the command runs without error, but no changes are seen in the title either by looking at Get Info or by using mdls on the command line.
The contents of my title.plist file is:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<string>Title2</string>
</plist>
The actual command I run to set the title is:
xattr -wx "com.apple.metadata:kMDItemTitle" "`xxd -ps title.plist`" "Put File Name Here.pdf"
Any thoughts where I might be doing something wrong?

OSX: Execute bash script when file appears in folder

I'm attempting to script my own screenshot uploader.
I am nearly there: OSX: Automatically upload screenshot to imageBin and put URL in clipboard
That script lets me write:
upload_image foo.png
And it will upload it, put a link to the URL in my clipboard, and make a noise
But I want it to be automatic. As soon as foo.png appears on my desktop, I need to execute '~/upload_image.sh foo.png'
How can I do this?
I'm interested in a Bash solution as it would allow me to merge with the target script, so I would only have one script file, which is clean. Also it would be multiplatform. Getting it to launch on start-up would be an issue.
I'm also interested in an AppleScript solution; I think the following script may be close:
on adding folder items to this_folder after receiving theFiles
-- If you want to do something with each file ...
repeat with aFile in theFiles
do shell script "~/upload_image.sh " &
end repeat
end adding folder items to
But I don't know how to pass 'aFile' into the command on the next line.
EDIT:
http://hardc0l2e.wordpress.com/2012/03/13/folder-monitoring-script-using-inotifywait/
In a small script to monitor a folder for new files, the script seems to be finding the wrong files
You can use Automator to create a folder action:
Or for example save this plist as ~/Library/LaunchAgents/example.plist:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>example</string>
<key>ProgramArguments</key>
<array>
<string>say</string>
<string>a</string>
</array>
<key>WatchPaths</key>
<array>
<string>~/Desktop/</string>
</array>
</dict>
</plist>
Then run launchctl load ~/Library/LaunchAgents/example.plist to load the plist. To apply changes to the plist, unload and load it. More information:
https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man5/launchd.plist.5.html
https://developer.apple.com/library/mac/technotes/tn2083/_index.html
http://osxnotes.net/launchd.html
A third option is to use Hazel:
Save screenshot to ~/screens/
defaults write com.apple.screencapture location ~/screens/
killall SystemUIServer
Save ss2CB.plist to ~/Library/LaunchAgents/
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Disabled</key>
<false/>
<key>Label</key>
<string>copy Screen Shots to ClipBoard</string>
<key>ProgramArguments</key>
<array>
<string>/usr/local/bin/python</string>
<string>~/ss2cb.py</string>
</array>
<key>WatchPaths</key>
<array>
<string>~/screens/</string>
</array>
</dict>
</plist>

Run applescript in Automator

I need to start and stop a small server with automator but my knoledge is very limited. I can't manage to set the path where the file is and I don't know how to stop the server.
So far I have this:
on run
set r to display dialog "Start or stop the NINJAM server ?" buttons {"Stop", "Start"}
if button returned of r is "Start" then
#tell application "Terminal"
# activate
do shell script "cd \"/Applications/ MUSIC/ Utilities/Audio IP/NINJAM/NINJAM/NinjamOSXServer ./ninjamsrv Server.cfg\""
#end tell
else
do shell script "Stop"
end if
end run
Any help is really apprectated. Thanks in advance.
NOTE that I'm using my own path here -- I put the ninjam server folder in the top level of my Applications folder.
I had to create a 'term' file, which is a text file with this in it:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>WindowSettings</key>
<array>
<dict>
<key>ExecutionString</key>
<string>cd /Applications/NinjamOSXServer/;./ninjamsrv config.cfg</string>
</dict>
</array>
</dict>
</plist>
I saved this as LaunchNinjamSrvr.term and put it in the same folder as the ninjamsrvr. Then the script to use is:
set r to display dialog "Start or stop the NINJAM server ?" buttons {"Stop", "Start"}
if button returned of r is "Start" then
do shell script "open /Applications/NinjamOSXServer/LaunchNinjamSrvr.term"
else
do shell script "killall -INT -v ninjamsrv"
end if
[Occurs to me that I should give some explanation. Directly using the full path with the " config.cfg" parameter makes 'do shell script' choke. Splitting into two commands (but still using do shell script), like you see in the .term file, works to launch ninjamsrv, but makes the script editor (I use Smile) freeze. So that is (presumably -- I didn't want to test it by other means [script app, etc.]) a problem, and why I resorted to using the .term file. It used to be that you could, from the File menu in Terminal (as I recall), save a .term file directly, but that seems to have fallen by the way-side. So, at this point, I have a template that I use and just paste commands into the appropriate line. (But see http://discussions.apple.com/thread/3139585?start=0&tstart=0 -- wherein the technique of exporting Terminal Preference file is explained). I'm being a bit lazy in that the new form is .terminal, not .term ... anyway ...
So now all that is left is doing the actual AS script. 'open' is a basic command line command which is just like opening or double-clicking in the Finder. If, for some reason your file opens in the wrong app or doesn't open, you might need to map it to Terminal.app (in the get info window) and/or change the extension to the more up--to-date '.terminal'.
killall is like kill, designed to kill processes in various ways. I chose -INT because this is essentially like doing a control-c to interrupt the process.]

Setting environment variables (specifically the PYTHON PATH) on a mac

Because it was such a mission to get this simple bit of info I've decided to post it for others:
In terminal execute: mkdir ~/.MacOSX
In terminal execute: touch ~/.MacOSX/environment.plist
Browse to the file and open.
Paste:
<key>DISPLAY</key>
<string>:0.0</string>
<key>PYTHONPATH</key>
<string>/full/path/ofyour/favorite/script/dir:/full/path/of/another/script/dir:
Edit to what you need and save.
Here is the documented way to do it with Property List Editor.
Note that you should use caution when setting environment variables this way as they apply to launched GUI applications which might not be expecting them. For setting default environment variables when working in a terminal shell, the conventional UNIX way of using shell profile commands, like .profile or .bash_profile is preferred and less likely to break things.
In terminal execute: mkdir ~/.MacOSX
In terminal execute: touch ~/.MacOSX/environment.plist
Browse to the file and open.
Paste:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>DISPLAY</key>
<string>:0.0</string>
<key>PYTHONPATH</key>
<string>/full/path/ofyour/favorite/script/dir:/full/path/of/another/script/dir:</string>
</dict>
</plist>
Edit to what you need and save.
(This was written by the original poster as part of the question. Reposted as community wiki because I didn't write it, just cleaned up the formatting.)

How do I make the dock icon stop bouncing after my app wrapper script starts?

So I recently made an .app wrapper for a zsh script, but when I run it, the icon for the app keeps hopping in the Dock.
The app is basically:
% find Example.app -type f
Example.app/Contents/Info.plist
Example.app/Contents/MacOS/wrapper.sh
% cat Example.app/Contents/Info.plist
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<!-- tell OSX what the name of the executable is -->
<key>CFBundleExecutable</key>
<string>wrapper.sh</string>
</dict>
</plist>
% cat Example.app/Contents/MacOS/wrapper.sh
#!/usr/bin/env zsh
# not my real script, but something else that hangs for a while
sleep 10
%
You can also grab it from github.
Is there any way I can get the app icon to stop hopping, and act like a normal app, and just sit there
with a triangle next to it?
An application's icon will bounce in the OS X Dock until the app enters its main event loop and begins responding to user input. As your script probably doesn't run a Carbon or Cocoa event loop (See documentation for Carbon Event Manager and NSApplication, respectively), the Dock is waiting continuously, expecting a regular foreground GUI application to emerge.
A script-wrapping tool that I've had success with is Platypus. It can run its own event loop while executing your script, and do a number of other convenient things.
You want DropScript. The dock doesn't work with shell scripts like that, it expects something a bit more full-fledged.
I think if you add LSUIElement to your Info.plist file, it should work.

Resources