Set Up
I am having an odd problem.
I have a website and I am hoping to run a python script when someone presses a button.
So, I have followed this tutorial: https://www.npmjs.com/package/python-shell
Question:
My console prints this: ReferenceError: require is not defined
on this line: var PythonShell = require('python-shell');
This is the first line in my .js function. I added this line after the npm install step.
How do I overcome this error?
Potentially Helpful Notes
My script looks like this:
angular.module('MYApp')
.controller('MyTypeController', function ($scope, $http, $stateParams, $state) {
$scope.runPythonRoutine = function () {
console.log("Error 1");
var PythonShell = require('python-shell');
var myshell = new PythonShell.run('hello.py', function (err, results) {
console.log("Error 2");
// script finished
});
};
...
My package.json contains:
...
"node-uuid": "1.4.7",
"python-shell": "^0.5.0",
...
require() does not exist in the browser/client-side JavaScript. You need require.js to use require() in the browser. You must also add this to package.json:
"require.js": "version"
and specify require.js in the <script> tag of the html code at the bottom, like so:
<script src="/location/of/require.js/"></script>
Related
The problem
I am creating an Electron-React frontend for my Python script.
Electron and Python communicate via Node.js child_process module, using the function spawn to call my Python script.
The script does the following task:
Gets path to a folder, which contains 15 pdf files.
Loads 1 pdf file at a time.
Skims through it to find the first word of the 5th page.
Saves the result in a list.
Continues until all pdf files have been read.
As you can see, this takes some time to process this script.
What I want to do: Once the process is called from Electron, I want the progress bar to appear, indicating how many pdf files are processed out of the 15 given. For example: 1/15 done, 2/15 done, and etc.
I tried googling the answer but after a week I'm at my wits end. I would very much appreciate any help I could get.
Disclaimer: I know of other good packages like Python Eel which does the job (sort of, in a hackish way). But I really want it to work with CLI.
The setup
I used Electron React Boilerplate for my purposes.
For simplicity I used a dummy function for python:
assets/python/main.py
import sys
import time
# Track the progress
progress = 0
def doStuff():
# Access the global variable
global progress
# Simulate time taken to do stuff. Set at 30 seconds per iteration.
for i in range(15):
progress += 1
time.sleep(30)
# The result
return "It is done!"
# Print is used to get the result for stdout.
print(doStuff())
src/main/main.ts
import { spawn } from 'child_process';
import path from 'path';
import { app, BrowserWindow, ipcMain, webContents } from 'electron';
...
let mainWindow: BrowserWindow | null = null;
...
app
.whenReady()
.then(() => {
ipcMain.handle('readPdfs', async (event, arg) => {
// Spawn a python instance
const python = spawn('python', [
path.join(__dirname, '..', '..', 'assets', 'python', 'main.py')
]);
// Get the result and pass it on to the frontend
python.stdout.on('data', (data) => {
const result = data.toString('utf8');
mainWindow.webContents.send('output', result);
});
});
...
src/main/preload.ts
import { contextBridge, ipcRenderer, IpcRendererEvent } from 'electron';
...
let mainWindow: BrowserWindow | null = null;
...
contextBridge.exposeInMainWorld('electron', {
...
// Just sending a command forward and getting a response.
readPdfs: async () => ipcRenderer.invoke('readPdfs'),
readPdfsOutput: (callback: any) => ipcRenderer.on('output', callback),
});
src/renderer/App.tsx
const Hello = () => {
const [text, setText] = useState('');
const handleReadPdfs = async (): Promise<void> => {
await window.electron.readPdfs();
await window.electron.output((event: any, response: string) => {
setText(response);
});
};
The question
What I have set up works. I manage to get the "It is done!" message all right. The problem is I want to get the value progress from main.py every time it increments, while the process is busy reading the pdfs.
Is there a way to get that value from the python script using child_process without interrupting a time consuming process?
I'm working on a project base on java. And the java program will run command to call a python script.
The python script is used tabula-py to read a pdf file and return the data.
I tried the python script was work when I direct call it in terminal (pytho3 xxx.py)
However, when I tried to call the python script from java, it will throw error:
Error from tabula-java:Error: File does not exist
Command '['java', '-Dfile.encoding=UTF8', '-jar', '/home/ubuntu/.local/lib/python3.8/site-packages/tabula/tabula-1.0.5-jar-with-dependencies.jar', '--pages', 'all', '--lattice', '--guess', '--format', 'JSON', '/home/ubuntu/Documents/xxxx.pdf']' returned non-zero exit status 1.
I tried to call the script in full path, provide the pdf file in full path, tried sys.append(python script path) and both of them are not worked.
I've tried to call the tabula in java command, i.e. java -Dfile.encoding=UTF8 -jar /home/ubuntu/.local/lib/python3.8/site-packages/tabula/tabula-1.0.5-jar-with-dependencies.jar "file_path"
And it's work and can read the file. However back to java to call the python script is not work
Is there any method to solve this? Use the tabula in java program is not an option for my case
Now that you mention that you mention you use java for base code and python for reading PDF, It's better of using java entirely for more efficient code. Why? Because there are tools already ready for you. There is absolutely no need for struggling to link one language to another.
code:
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.parser.PdfTextExtractor;
/**
* This class is used to read an existing
* pdf file using iText jar.
*/
public class PDFReadExample {
public static void main(String args[]){
try {
//Create PdfReader instance.
PdfReader pdfReader = new PdfReader("D:\\testFile.pdf");
//Get the number of pages in pdf.
int pages = pdfReader.getNumberOfPages();
//Iterate the pdf through pages.
for(int i=1; i<=pages; i++) {
//Extract the page content using PdfTextExtractor.
String pageContent =
PdfTextExtractor.getTextFromPage(pdfReader, i);
//Print the page content on console.
System.out.println("Content on Page "
+ i + ": " + pageContent);
}
//Close the PdfReader.
pdfReader.close();
} catch (Exception e) {
e.printStackTrace();
}
}
Ok I'm fairly new to swift and am trying to create an app with a button that uses python. I have seem code looking like
//
// ContentView.swift
// Shared
//
// Created by Ulto4 on 10/17/21.
//
import SwiftUI
import PythonKit
struct ContentView: View {
#State private var showDetails = false
#State var result : String = " "
var body: some View {
HStack{
Text("Hello, world!")
.padding()
Button(action : {
self.coolPerson()
}, label: {
Text("Respones")
})
Text("\(result)")
}
}
func coolPerson(){
let sys = Python.import("sys")
sys.path.append("/Users/ulto4/Documents/vsc")
let example = Python.import("ahhhhh")
let response = example.hi()
result = response.description
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
.preferredColorScheme(.dark)
}
}
The code in the python file is
def hello():
return "cool"
However, when I click the button I get this error
2021-10-17 17:53:16.943097-0700 GAAIN[27059:2277939] PythonKit/PythonLibrary.swift:46: Fatal error: Python library not found. Set the PYTHON_LIBRARY environment variable with the path to a Python library.
(lldb)
I also clicked the .xcodeproj and deleted the Apple Sandbox. But it still doesn't work. Since I'm fairly new I don't know how to do this. Any help would be appreciated.
EDIT: As per the comments, IOS doesn't support PythonKIT
We have a c#/.net Windows service that parses big log files for us and updates a meta table when it does so. The problem is whenever you need to stop the service or (services, we have multiple of them running), one must manually delete the files that are in the process of being parsed in the local folder and also update the queue DB table where it tracks files to process.
I want to automate this. I am much more familiar with python so ideally, it would be a python script as opposed to .net. Is it possible to have a script that will trigger when the service is stopped? How would one do this?
I have tried doing this internally in the .net service but since it's multithreaded, files don't get cleaned up neatly. There's always a "can't stop service because another process is using it". It is like the service gets stuck trying to delete files when the Onstop() method is called. This was how I had tried to do it internally within the service:
protected override void OnStop()
{
ProducerConsumerQueue.Dispose();
Logger.Info($"{ProducerConsumerQueue.Count()} logs will be canceled");
CancellationTokenSource.Cancel();
FileUtil.DeleteFilesInProgress(Constants.ODFS_STAGING);
MetadataDbContext.UpdateServiceEntriesOnServiceReset();
//look into some staging directory, delete all files.
Logger.Info($"{ProducerConsumerQueue.Count()} logs canceled");
}
public static void DeleteFilesInProgress(string directory)
{
var constantsutil = new ConstantsUtil();
constantsutil.InitializeConfiguration();
try
{
System.IO.DirectoryInfo di = new DirectoryInfo(directory);
foreach (FileInfo file in di.GetFiles())
{
file.Delete();
}
}
catch(Exception ex)
{
Logger.Error(ex.Message);
string subject = Constants.GENERAL_EMAIL_SUBJECT;
string body = "The following error occured in Client.Util.ConstantsUtil:";
string error = ex.ToString(); //ex.ToString makes it more verbose so you can trace it.
var result = EmailUtil.Emailalert(subject, body, error);
}
}
public static int UpdateServiceEntriesOnServiceReset()
{
int rowsAffected = 0;
try
{
string connectionString = GetConnectionString();
using (SqlConnection connection = new SqlConnection())
{
connection.ConnectionString = connectionString;
SqlCommand cmd = new SqlCommand();
cmd.CommandType = CommandType.Text;
cmd.CommandText = $"UPDATE {Constants.SERVICE_LOG_TBL} SET STATUS = '0'";
cmd.Connection = connection;
connection.Open();
rowsAffected = cmd.ExecuteNonQuery();
}
}
catch (Exception ex)
{
Logger.Error($"{ex.Message.ToString()}");
string subject = Constants.GENERAL_EMAIL_SUBJECT;
string body = "The following error occured in Client.MetadatDbContext while Parser was processing:";
string error = ex.ToString(); //ex.ToString makes it more verbose so you can trace it.
var result = EmailUtil.Emailalert(subject, body, error);
}
return rowsAffected;
}
You can run your script from OnStop:
using System.Diagnostics;
Process.Start("python yourscript.py");
// or whatever the command for executing your python script is on your system.
And then use something like pywin32's win32service to find out the status of the service that launched the script, and then wait for it to die and release its hold on the files.
Then wipe them.
I want to customize code in im_chat.js -> im_chat.ConversationManager with my own javascript file, not changing any code from im_chat.js file.
Can anyone tell me good practice on how to do this?
Here are the functions i want to customize:
List item
window_title_change
apply_session
activate_session
delete_session
received_message
Try this method:
openerp.your_module = function(instance) {
im_chat.ConversationManager.include({
window_title_change : function(){
//Your code
}
});
};