In this post we explore two ways to run a python script from Photoshop providing arguments (like the Photoshop file name). Those simple scripts helped us create complex behaviours to process results of Photoshop scripts for the Set department of the feature film Dilili in Paris or in our recent project for the Lodève Museum. The background artists could work in Photoshop and start those procedures without exciting software. Using such scripts to push previews to the production manager software, moving files, starting a blender playblast to get a preview of the updated scene, etc. Saving a lot of time.
Three components are needed to execute python code from Photoshop providing arguments:
- A Photoshop script, in our case using javascript (working on both Mac and Windows OS)
- An executable, like a .bat for Windows or .command for mac, that Photoshop can call
- And, of course, your python script (and python installed)
You can use the Adobe ExtendScript Toolkit provided with your software to try and debug scripts before saving them in the Presets > Scripts-folder of you install folder. So you can try before simply accessing the script through File/Scripts/YourScript (for which you can also assign a keyboard shortcut, add it in an action, etc).
The Environment Variable Way
First is the Photoshop javascript .jsx code. In this example we will just have a very simple argument provided to the python script: the Photoshop filename. But it could be anything. The way we push info out of Photoshop is setting a temporary environment variable that the .bat can use.
We then set a temporary environment variable with the $.setenv(VARIABLE_NAME, VARIABLE_VALUE)
Photoshop javascript function, and when we execute the bat file, the command prompt launched has access to that variable.
// Get the active document name var theDoc = app.activeDocument; // Just the name, not the path var docName = theDoc.name.replace(/\..+$/, ''); // path of the bat file to execute var batPath = "C:\\path\\to\\bat_file.bat"; // this is were we set the environment variable $.setenv("DOC_NAME", docName); // and we now execute the bat file File(batPath).execute();
Now the bat file is pretty easy. On Windows, environment variables can be passed as argument using %variableName%
. So we can just call a python script providing the variable content argument.
@echo off // to avoid useless prints python my_python_script.py %DOC_NAME%
In that case, the command prompt will be open, run the python script, and close itself immediately. Even if the python script failed. You might add a sleep 10
at the end of your script to keep the window open for 10 seconds, or use a more advanced choice
command
Of course you can set a more complex call with many arguments. We use optparse
but any other solution can be used to collect the arguments. Or you could use os.environ
to get the variables within your python script. In that case, os.environ['DOC_NAME']
can be used instead of providing the name in the python command.
From there, you are free to do anything python can do. For example, we had the case of opening a GUI wizard to ask something else to the user, like one background set could be used by many shots with different cameras and you might want to see an update for all of them or only one. That could be done with Qt/PySide, or even the good old Tkinter (for very simple things).
The Temporary Executable Batch
We had to translate some tools from Windows to Mac OS. But the environment variable was not working as expected, as the call made to the terminal app was different. We could have digged for a solution, but we moved to another way that can also be used on Windows: writing, on the fly, a temporary .command or .bat file, with the arguments, and then execute it.
The good point is you can save that in a folder, and later access the command, to re-execute it if needed. You might use that in many ways to keep track of what was executed and when. Not only from Photoshop. These executable files are very light and easy to save.
This example applies for Mac .command files. But you can do the equivalent with .bat files.
// Same as before, we gather the information we need // Get the active document name var theDoc = app.activeDocument; // Save the name without fullpath var docName = theDoc.name.replace(/\..+$/, ''); // we set the path to our temporary .command (Mac equivalent of .bat) // we use the current date time as string in the filename var date = Number(new Date()); var execFilePath = "/path/to/command/photoshop-exec_"+ date +".command" // we create the command file, and setup it before opening it var execFile = new File(execFilePath); execFile.encoding = "UTF-8"; execFile.lineFeed = "Unix"; execFile.open("w"); // now we write on the .command file, // that it's a bash script, calling python with an argument execFile.write( "#!/bin/bash\n\n" + "python my_python_script.py " + docName); // you can repeat that command and write many lines instead // when the file is written, we simply execute it File(execFilePath).execute();
That’s it!
To conclude
So we have seen two different ways of executing a python command from Photoshop. On our project we used that, combined with more usual Photoshop commands, exporting groups of layers as separated pngs, exporting a preview, saving a sanitised photoshop file. Then the python script was used for pushing information and a preview to our production tracking software. Or even launch a Blender playblast to preview the updated set quickly. So a 2D artist not knowing Blender could get an update without anyone else’s help.
For us, the future might be with Krita, as it now has embedded Python, and we can create powerful tools. The most difficult aspect will be to get our background team toget used to that new tool.
3 Comments
Toke Jepsen
Very interesting! Thanks for sharing 🙂
I did a After Effects to Python (Pyblish) bridge once (long time ago) where the user would select a ExtendScript which would open a client/server connection, where you could send ExtendScript commands to AE and get the results back into Python (Pyblish).
https://github.com/pyblish/pyblish-aftereffects/pull/1/files
Flavio Perez
Hi! Waw thanks for sharing that script you made too! It looks very interesting too and I definitely have a look soon. Might be useful to do some tests with it in the future 🙂
I had a similar approach when working on creating tools for blender outside of blender, using websockets. Part 2 with practical examples is still to be made, but the concept was explained here. Cheers!
jeremy bepoix
Hi,
Well explain, thank you !
Just a note to correct batch exec() :
“`
// when the file is written, we simply execute it
File(execFilePath).execute();
“`
into this :
“`
// that it’s a bash script, calling python with an argument
execFile.writeln(
“#!/bin/bash\n\n” +
“python my_python_script.py ” + docName);
execFile.close();
// you can repeat that command and write many lines instead
// when the file is written, we simply execute it
execFile.execute();
“`
Need to take File and not FilePath.
regards,