calling python script from node.js - python

I want to call python script from node.js
Here is my script : my.py
def printme( str ):
# print str;
return str;
printme("I'm first call to user defined function!");
printme("Again second call to the same function");
My node script : testpy.js
var PythonShell = require('python-shell');
var pyshell = new PythonShell('my.py');
pyshell.on('message', function(message) {
console.log(message);
});
but getting error
events.js:85
throw er; // Unhandled 'error' event
Error: spawn python ENOENT
at exports._errnoException (util.js:746:11)
at Process.ChildProcess._handle.onexit (child_process.js:1046:32)
at child_process.js:1137:20
at process._tickCallback (node.js:355:11)
at Function.Module.runMain (module.js:503:11)
at startup (node.js:129:16)
at node.js:814:3
P.S I have install Python shell
Also if I want to execute individual function from node.js to python script. can I do that ?Help

You can simply write the 'my.py' file like this-
def printme(str):
return str;
print(printme("I'm first call to user defined function!"));
Check if the path given is correct and check for indentation errors.

Your print statement (my.py line 2) is commented out so nothing will be output and the message event will therefore never fire. Uncomment your print statement, the Node PythonShell object will redirect the stdout (which print writes to) and fire a message event with the output.
As for your error, it looks like the python script isn't being found in the current directory. See https://docs.python.org/2/library/errno.html for error codes and what they mean. Make sure your script is in the right directory or set your python shell to the correct directory using os.chdir.

I think that you need to set up the python script to take in standard input like this
import sys
for v in sys.argv[1:]:
print v
Also when setting up the code the way you have it you need to do a PyhtonShell.send('message'), but I would need to see more of your code because I don't see how you are sending data to the python shell through Node.js.

You can simply import Npm Pythonshell using let keyword instead of const Keyword.
let {PythonShell} = require('python-shell')
this works for me

Related

How to initialize JS variables through Selenium python?

I am trying to execute a JS file through python, selenium but I think I miss something.
I tried to call the checking variable from safari console, but it shows the following error Can't find the checking variable.
I also tried to execute the following code line driver.execute_script('var checking=0;') but I got the same result when I tried to call the checking variable from Safari Console.
PYTHON CODE
driver.execute_script(open("/Users/Paul/Downloads/pythonProject/Social media/javascripts/Initializing Variables.js").read())
JS FILE
var checking;
function Checking(item) {
if (item) {
checking = true;
}
else {
checking = false;
}
}
Any ideas?
All variables will be available just in single execute_script command context. So it's not possible to define variable in one driver command and modify it or get by another, unless you put the data to document, localstorage or sessionstorage..
But you're able to declare and put something to the variable, just don't forget to return it's value in script.
If I execute this script with driver.execute_script
var a;
function setAValue(arg) {
a = arg;
}
setAValue(100);
return a;
you'll get 100 in the output result.
And if you want to run your file from script, the file should ends with the function invocation and the return statement.
Share function and variables between scripts
This is working example in groovy language (sorry no python env)
WebDriverManager.chromedriver().setup()
WebDriver driver = new ChromeDriver()
driver.get("https://stackoverflow.com/")
//define variable date and function GetTheDatesOfPosts
driver.executeScript('''
document.date = [];
document.GetTheDatesOfPosts = function (item) { document.date = [item];}
''')
//use them in new script
println (driver.executeScript('''
document.GetTheDatesOfPosts(7);
return document.date;
'''))
driver.quit()
it prints [7].
Here's a quick tutorial on local vs globally scoped variables.
If you run a command such as:
self.execute_script("var xyz = 'abc';")
and then go to the console to try to find xyz, it won't be there (xyz is not defined).
However, if you run:
self.execute_script("document.xyz = 'abc';")
then it will be in the browser console if you type document.xyz.
That's the short summary. If you just try to declare a local variable when run from execute_script, then it'll go out-of-scope after the script is run. However, if you attach a variable to a persistent one, that's one way of keeping the variable around (and still accessible).

How to run C# Console Applications via Python?

I've created the following C# Console Application (.NET Core 3.1) with Visual Studio:
using System;
namespace ConsoleApp2
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Hello World!");
//Check if args contains anything
if (args.Length > 0)
{
Console.WriteLine("args = " + args[0]);
} else
{
Console.WriteLine("args is empty");
}
//Prevent the application from closing itself without user input
string waiter = Console.ReadLine();
}
}
}
I am able to execute the application succesfully with one argument via cmd.exe:
CMD Input and Output
Now I'd like to run this program with one argument via Python. I've read How to execute a program or call a system command? and tried to implement it. However, it seems that the application is not being run properly.
The python code I am using via Jupyter notebook:
import subprocess
path = "C:/Users/duykh/source/repos/ConsoleApp2/ConsoleApp2/bin/Release/netcoreapp3.1/ConsoleApp2.exe"
subprocess.Popen(path) //#Also tried with .call and .run
//#subprocess.Popen([path, "argumentexample"]) doesn't work either
Output:
<subprocess.Popen at 0x2bcaeba49a0>
My question would be:
Why is it not being run (properly) and how do I properly run this application with one argument?
I've answered my own question. In a nutshell: I am pretty stupid.
Jupyter Notebook was running in the background and the application was being run there. That's why it didn't open a new prompt.
subprocess.Popen([path, "argument example"]) seems to work well for running a console application with an argument as input.

Can't find module: Python, NodeJS, and fs module

With Python, I make a script that asks for input (an action). The second option runs a NodeJS file called settings.js in a new terminal window with:
subprocess.call('start node src/settings.js', shell=True)`
In the NodeJS settings.js file, it basically uses fs to overwrite a key's value in config.json. In this case, change the key "PREFIX" to whatever the user inputs (e.g. !).
When it first reads the config.json file, it shows an error.
Code:
await fs.readFile('config.json', 'utf8', async (err, data) => {
// code to overwrite (with given data)
}
Error:
[Error: ENOENT: no such file or directory, open 'C:\Users\userhere\Desktop\serenity-zero\serenity-zero-test\config.json'] {
errno: -4058,
code: 'ENOENT',
syscall: 'open',
path: 'C:\\Users\\userhere\\Desktop\\serenity-zero\\serenity-zero-test\\config.json'
}
I figured that this happened as it originally ran from the python script, so the directory folder was outside of the NodeJS file (the python script's folder directory). I tried:
await fs.readFile('src/config.json', 'utf8', async (err, data) => {
// code
});
and,
await fs.readFile('./src/config.json', 'utf8', async (err, data) => {
// code
});
But, I got:
(node:17348) UnhandledPromiseRejectionWarning: Error: Cannot find module './src/config.json'
Require stack:
- C:\Users\userhere\Desktop\serenity-zero\serenity-zero-test\src\settings.js
at Function.Module._resolveFilename (internal/modules/cjs/loader.js:880:15)
at Function.Module._load (internal/modules/cjs/loader.js:725:27)
at Module.require (internal/modules/cjs/loader.js:952:19)
at require (internal/modules/cjs/helpers.js:88:18)
at C:\Users\userhere\Desktop\serenity-zero\serenity-zero-test\src\settings.js:29:87
at FSReqCallback.readFileAfterClose [as oncomplete] (internal/fs/read_file_context.js:63:3)
(Use `node --trace-warnings ...` to show where the warning was created)
(node:17348) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 1)
(node:17348) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
Just so you know, this worked perfectly fine when the python script was in the same folder as the node.js files. I wanted to make it more organized so I put the node.js files in a src folder. The python script remained in the original folder. After that, I got this error.
Just fixed it, all I had to do was put the config.json in the same directory as the launch.py file. I don't think it's possible for the config.json to be in the src folder, but atleast it works.

spawn python ENOENT error with node child process

I am trying to call a python script as a child process within a node script. The output of the script is to be used within a callback. The code looks like this:
//myFunction.js
const myFunction = callback => {
let py = process.spawn('python', ['../folder/pyscript.py'], {
cwd: '../folder/'
});
let str = '';
py.stdout.on('data', data => {
str += data.toString();
}
py.stdout.on('end', () => {
callback(str);
}
}
exports.myFunction = myFunction;
This code works as expected when I directly run node myFunction.js (with an instance of myFunction within the script) and it works fine when I require the module in any other files within the same directory as myFunction.js.
But it fails with the following error when the module is required in a different higher level directory:
error: spawn python ENOENT
I'm guessing this has something to do with paths (value of cwd maybe?) but I can't seem to fix this. I've looked up similar questions but the answers aren't helping.
Any help will be appreciated. :)
Apparently, the issue is with the cwd. Everything in the script is relative to the path of the directory from where the script is invoked. So basically, running node myFunction.js from the project root directory (say ~/projects/myProject would set the cwd to ~/projects/myProject/../folder which would evaluate to ~/projects/folder. This is obviously incorrect, since in all probability, no directory named folder exists on the system, and thus this would lead to an ENOENT error.
The solution would be to construct the absolute path of your script in the code, perhaps by using the __dirname__ property in combination with the functionalities provided by the path module.
I struggled with this issue for days, before realizing that my script file was not getting picked up and spawned by nodeJS, because of some filepath issue.
Although I don't guarantee this will work for everyone, depending on their setup, this is what I did in my nodejs file:
let py = process.spawn('python', [__dirname + '../folder/pyscript.py']);
As you can see, I didn't have to use the {cwd: '../folder/'} option.
If your script is in the current directory as your javascript file, just do
let py = process.spawn('python', [__dirname + './pyscript.py']);
I should also point out that:
process.spawn('python', ['./pyscript.py']);
never worked for me and I spent days wondering why. Could find an answer until I tried this technique. Hope someone having this issue find this answer useful.
Using ${process.cwd()} worked for me... you can write it like this
let py = process.spawn('python', [`${process.cwd()}/folder/pyscript.py`]});

pass parameter to PowerShell script when calling from Python

From python I want to call a powershell script and pass a parameter to it
The Powershell function header is listed here:
Function Invoke-Neo4j
{
[cmdletBinding(SupportsShouldProcess=$false,ConfirmImpact='Low')]
param (
[Parameter(Mandatory=$false,ValueFromPipeline=$false,Position=0)]
[string]$Command = ''
)
Python - How do pass the parameter $Command = 'start' to the function from python? I can't seem to get it to work.
import subprocess
cmd = ['powershell.exe', '-ExecutionPolicy', 'RemoteSigned', '-File',
'C:\\PathName\\Invoke-Neo4j.ps1']
returncode = subprocess.call(cmd)
print(returncode)
I couldn't make the Powershell command work from Python. I actually found a .bat file with a command that works. I just inserted the 'start' parameter I call the bat file from python. It works like a charm. It's not optimal but it does the job for me.
SETLOCAL
Powershell -NoProfile -NonInteractive -NoLogo -ExecutionPolicy Bypass -Command "try { Unblock-File -Path '%~dp0Neo4j-Management\*.*' -ErrorAction 'SilentlyContinue' } catch {};Import-Module '%~dp0Neo4j-Management.psd1'; Exit (Invoke-Neo4j 'start')"
EXIT /B %ERRORLEVEL%
Running a script, in either PowerShell or Python, that only defines a function but does not call it has no other effect than defining function. The script needs to include a specific call to that function. In your case, you might as well put the logic at the top level of the script instead of inside a function then calling the function. This would look like:
[cmdletBinding(SupportsShouldProcess=$false,ConfirmImpact='Low')]
param (
[Parameter(Mandatory=$false,ValueFromPipeline=$false,Position=0)]
[string]$Command = ''
)
# rest of code not surrounded by { }
exit 0
Invoke the revised script from Python as you were initially doing and it should work properly.

Categories