Execute external script in ExtendScript for Illustrator - python

Summary:
Is there a way to use the execute() function to pass a parameter to a Python script, and have the Python script use the parameter in its execution, then return the result to ExtendScript?
Context:
I'm building a script for Illustrator that has to query a web service, process the resultant XML file, and return the results to the user. This would be easy if I were using one of the applications that support the Socket feature, but Illustrator doesn't. My next thought, was that I can achieve the HTTP request and XML parsing in Python. I'm at a loss on how to bridge the two.

Option 1 (BridgeTalk)
I had to do something like this to run an external PNG processor from both Photoshop and Illustrator. Neither of those applications have the ability to execute external programs from ExtendScript. (See Option 2.) Adobe Bridge's app object has a system method that executes a command in the system shell. Using a BridgeTalk object, you can call that method remotely from Illustrator. You'll only get the exit code in return, though. So you'll need to redirect your program's output to a file and then read that file in your script.
Here's an example of using BridgeTalk and Adobe Bridge to run an external program:
var bt = new BridgeTalk();
bt.target = 'bridge';
bt.body = 'app.system("ping -c 1 google.com")';
bt.onResult = function (result) {
$.writeln(result.body);
};
bt.send();
Pros
Asynchronous
Can easily retrieve the exit code
Can use shell syntax and pass arguments to the program directly
Cons
Adobe Bridge must be installed
Adobe Bridge must be running (although BridgeTalk will launch it for you, if needed)
Option 2 (File.prototype.execute)
I discovered this later and can't believe I missed it. The File class has an execute instance method that opens or executes the file. It might work for your purposes, although I haven't tried it myself.
Pros
Asynchronous
Built into each ExtendScript environment (no inter-process communication)
Cons
Can't retrieve the exit code
Can't use shell syntax or pass arguments to the program directly

Extendscript does support Socket, following is the code snippet
reply = "";
conn = new Socket;
// access Adobe’s home page
if (conn.open ("www.adobe.com:80")) {
// send a HTTP GET request
conn.write ("GET /index.html HTTP/1.0\n\n");
// and read the server’s reply
reply = conn.read(999999);
conn.close();
}

Related

Using an API / WebService in Python instead of C#

I have to use a Webservice, where on my own webserver a script should make GET requests regularly. There exists a documentation with multiple C# examples. This should work (I could not get it running on my windows pc).
https://integration.questback.com/integration.svc
You have created a service.
To test this service, you will need to create a client and use it to call the service. You can do this using the svcutil.exe tool from the command line with the following syntax:
svcutil.exe https://integration.questback.com/Integration.svc?wsdl
This will generate a configuration file and a code file that contains the client class. Add the two files to your client application and use the generated client class to call the Service. For example:
C#
class Test
{
static void Main()
{
QuestBackIntegrationLibraryClient client = new QuestBackIntegrationLibraryClient();
// Use the 'client' variable to call operations on the service.
// Always close the client.
client.Close();
}
}
Since the server is linux based and I don´t know a piece of C# + XML, I wanted to ask if there is an way to make this run on linux server, preferable with Python (I know this question is quite vague, I´m sorry).
Thank you!

How to have a Python Script run constantly in the background connected to a Node.JS server

Currently I have a Node.JS server that needs to run a python script. Part of this script imports some data from a server that takes time which is detrimental to the experience as this Python script needs to be ran frequently.
What I want is for the Node.JS server to run this Python script when the server is ran, then in the background constantly have it keep running, with the ability to (from the Node.JS server) call a python function that returns data.
So far I have this on the Node.JS server that runs a python script and outputs the response. This is repeated every time data is needed to be retrieved:
const util = require('util');
var options = {
mode: 'text',
args: [sentenceToUse]
};
const readPy = util.promisify(PythonShell.run);
const test = await readPy("spacyTest.py", options);
var response = test.toString();
response = response.toString();
response = response.replace(/'/g, '"');
response = JSON.parse(response);
return(response);
console.log(test);
'''
How can I keep this running in the background without restarting the python script every time data is needed?
It seems you need to change the python script itself to keep running and respond to requests from its parent. If the python script now runs and exits, there's nothing you can do from node.js to stop that. You need to change the python script.
Here are some options:
The python script can regularly send data back to its parent on stdout and you can read that data from nodejs as it arrives.
You can put a little local http server or socket.io server in the python script on a known port and have your nodejs parent communicate with that to make requests and get responses.
The Python-shell module also shows you how to communicate between node.js parent and the python script here in the doc, so that is an option too.
Since options 1 and 3 are built-in already, I would probably start with one of those until you find some reason they aren't sufficient.

Can I use Electron without node.js

Im new to Javascript so I would like to keep it at the bare minimum. Is there a way that I can use the Electron to communicate with python script without having node.js? My app is just a basic app that takes some input from users from a html page and I need this text input to be processed in python and write an excel file. So there is not much happening in html so is there a simple way to transfer the input to python file? I want to use Electron because I need this html to be my UI and also I need to distribute this app.
I guess the answer is "no": the main process running node will always be there.
An Electron app consists of a JavaScript main process, and one or more JavaScript renderer processes. There is no built-in Python support. And the user will need Python already installed. So, it sounds like a poor fit for what you need.
The answers here may be useful, and will show how to call the python script. I took a quick look at the flexx toolkit mentioned there. It seems to work with the user's browser, rather than producing a single executable.
Recently i have done it with some sort of trick hope it will help you and there are the following step which i followed-
Created a stand alone python exe using pyinstaller and the exe has flask server internally then i put the flask server inside my node application.
Now we have to initiate our flask server and send a request to it for processing, i have done this with the help of "execFile" function as a child process, for which i have created a function and the code was something like that-
async function callFlask(){
var child = require('child_process').execFile;
child('path_to_python_exe ', function(err, data) {
if(err){
console.error(err);
return;
}
});
}
Now we have initiated our flask server then will send the request with the help of fetch request like
await callFlask().then(
await fetch('host_ip_defined_in_flask'+encodeURIComponent('data'))
Now further we can extend our then chain to get response from python if any and proceed further forexample -
await callFlask().then(
await fetch('host_ip_defined_in_flask'+encodeURIComponent('data'))
.then(res => res.text())
.then(body => console.log(body)))
Here, your output data which python return will be printed in console then you can make your node application behave differently depending on output returned by it.
Also you can package your app with available packagers for electron like electron-packager it will work like a charm.
Also there is are some disadvantage for using python as like it will increase your package size and the process will be difficult to kill from electron after processing so it will increase burden on host machine.
I am assuming that Explaining to create a flask server is not the scope of this question instead if you face any issues let me know, i hope it will help...

python, how to run commands on remote hosts and show output in GUI in real time?

I know this is a real open-ended question, but I'm new to python and am building a simple one off web app to give a non technical team some self service capabilities. This team has a bunch of repetitive tasks that they kick over to another team that are just begging to be automated, like restarting a few processes on remote hosts, grep logs, cleanup old files, deploy/restart new versions of an application, get current running versions, etc. The users will be clicking buttons and watching the output in the GUI, they WILL NOT be manually entering commands to run (I know this is dangerous). Any new tasks will be scripted and added to the app from the technical support team.
Now, the only piece I'm not sure on is how to get (near) real time output from the commands back to the GUI. I've built a very similar app in PHP in the past, and what I did was flush the output of the remote commands to a db, and then would poll the db with ajax and append new output. It was pretty simple and worked great even though the output would come back in chunks (I had the output written to the GUI line by line, so it looked like it was real time). Is there a better way to do this? I was thinking of using web sockets to push the output of the command back to the GUI. Good idea? Bad idea? Anything better with a python library? I can also use nodejs, if that makes any difference, but I'm new to both languages (I do already have a simple python flask application up and running that acts as an API to glue together a few business applications, not a big deal to re-write in node).
This is a broad question, but I'll give you few clues.
Nice example is LogIo. Once you are willing to run some commands and than push output to GUI, using Node.js becomes natural approach. This app may contain few elements:
part one that runs commands and harvests output and pushes it to
part two that receives output and saves it to DB/files. After save, this part is throwing event to
part three, that should be a websocket server, which will handle users that are online and distribute events to
part four, which would be preoperly scripted GUI that is able to connect via websocket to part three, log-in user, receive events and broadcast them to other GUI elements.
Once I assume you feel stronger with PHP than python, for you easiest approach would be to create part two as a PHP service to handle input (save harvested output to db) and than, let say use UDP package to part three's UDP listening-socket.
Part one would be python script to just get command output and bypass it properly to part two. It should be as easy to hadle as usual grep case:
tail -f /var/log/apache2/access.log | /usr/share/bin/myharvester
at some point of developing it you will be in demand of passing there also user or unical task id as parameter after myharvester.
Tricky but easier than you think will be to create a Node.js cript as part three. As a single instance script it should be able to receive input and bypass it to users as events. I've commited comething like this before:
var config = {};
var app = require('http').createServer().listen(config.server.port);
var io = require('socket.io').listen(app);
var listenerDgram = require('dgram').createSocket('udp4');
listenerDgram.bind(config.listeners.udp.port);
var sprintf = require('sprintf').sprintf;
var users = [];
app.on('error', function(er) {
console.log(sprintf('[%s] [ERROR] HTTP Server at port %s has thrown %s', Date(), config.server.port, er.toString()));
process.exit();
});
listenerDgram.on('error', function(er) {
console.log(sprintf('[%s] [ERROR] UDP Listener at port %s has thrown %s', Date(), config.listeners.udp.port, er.toString()));
process.exit();
});
listenerDgram.on('message', function(msg, rinfo) {
// handling, let's say, JSONized msg from part two script,
// buildinf a var frame and finally
if(user) {
// emit to single user based on what happened
// inside this method
users[user].emit('notification', frame);
} else {
// emit to all users
io.emit('notification', frame);
}
});
io.sockets.on('connection', function(socket) {
// handling user connection here and pushing users' sockets to
// users aray.
});
This scrap is basic example of not filled with logic what-you-need. Script should be able to open UDP listener on given port and to listen for users running into it within websockets. Honestly, once you become good in Node.js, you may want to fix both part two + part three with it, what will take UDP part off you as harvester will push output directly to script, that maintains websocket inside it. But it has a drawback of duplicating some logic from other back-end as CRM.
Last (fourth) part would be to implement web interface with JavaScript inside, that connects currently logged user to socket server.
I've used similar approach before, and it is working real-time, so we can show our Call-Center employees information about incoming call before even phone actually start to ring. Finally solutions (not counting interface of CRM) closes in two scripts - dedicated CRM API part (where all logic happen) to handle events from Asterisk and Node.js event forwarder.

using python and node.js

I use to program on python. I have started few months before, so I am not the "guru" type of developer. I also know the basics of HTML and CSS.
I see few tutorials about node.js and I really like it. I cannot create those forms, bars, buttons etc with my knowledge from html and css.
Can I use node.js to create what user see on browser and write with python what will happen if someone push the "submit" button? For example redirect, sql write and read etc.
Thank you
You can call python scripts in the back end at the node server, in response to button click by user. For that you can use child_process package. It allows you to call programs installed on your machine.
For example here is how to run your script when user POST's something on /reg page:
app.post('/reg', function(request, response){
spawn = require('child_process').spawn;
path = "location of your script";
// create child process of your script and pass two arguments from the request
backend = spawn('python',[path, request.body.name, request.body.email]);
backend.on('exit', function(code) {
console.log(path + ' exited with code ' + code);
if(code==0)
response.render('success'); //show success page if script runs successfully
else
response.redirect('bad');
});
});
Python has to be installed in your system, along with other python libraries you will need. It cannot respond / redirect to requests to node, else why would you use node then. When in Rome, do as the Romans do. Use JavaScript in node, calling external programs is not as fast using JS libraries.
Node.js is a serverside JavaScript environment (like Python). It runs on the server and interacts with the database, generates the HTML that the clients see and isn't actually directly accessed by the browser.
Browsers, on the other hand, run clientside JavaScript directly.
If you want to use Python on the server, there are a bunch of frameworks that you can work with:
Django
Flask
Bottle
Web.py
CherryPy
many, many more...
I think you're thinking about this problem backwards. Node.js lets you run browser Javascript without a browser. You won't find it useful in your Python programming. You're better off, if you want to stick with Python, using a framework such as Pyjamas to write Javascript with Python or another framework such as Flask or Twisted to integrate the Javascript with Python.

Categories