I would like to be able to click an "Alert" button on my rails application that then calls python to run a specific alert script.
My specific question is how do I get the click event to call the python script?
Check this SO post: Call python script from ruby
ruby provides a variety of methods, exec, system that all take the path to the ,py file along with arguments. Something like
result = exec("python /path/to/script/script.py params")
Or
system 'python /path/to/script/script.py', params1, params2
Or even backquotes
`python /path/to/script/script.py foo bar`
Now, the question is where to put this? I am assuming you have a controller that handles clicks, and it is this controller where you put this code. Check this link out How to integrate a standalone Python script into a Rails application?
Now details depend a lot on your python script. By 'alert script', do you mean a Javascript alert() dialog, a flash msg or anything else? It's always a good idea to refactor your python code to return a string result and the use that in ruby-on-rails. Even better, as far as possible, write the alert-creating-script in ruby itself! It might not be possible in a 3rd-party library setting, but for a simple stand-alone script, it's worth the effort!
Related
This question already has answers here:
Which is the easiest way to simulate keyboard and mouse on Python?
(5 answers)
Closed 5 years ago.
I am searching for any module for OSX automation like opening any app via Python and controlling mouse, keyboard via Python etc. I tried with AppleScript but I was wondering if I can access mouse, keyboard and can automate any app on OSX using Python? I found pyauto, If there is any other good Python library, module for OSX automation please let me know.
I too am looking for a good python module to use 'applescript' within python. In fact this is how I got here. I was unable to find anything so I had to come up with my own solution.
What works well for me is to call osascript from within my python programme using the subprocess module.
More precisely, (see the code below for an example), if I want to add something to my calendar I generate the applescript that does it as string in my python programme and then pipe it into osascript.
This is not super elegant and probably also not super fast but it works well. So, I am currently writing a calendar module that has python functions for adding events, getting list of events .... and each generates the applescript as string and calls osascript.
It sounds terrible but works quite well and once you have a module for your favourite programme you don't need to worry anymore about applescript.
One needs a way to encode in the applescript the return data and then decode it in the python programme. As for me most data passed to and from the applescript are dictionary-like, this has not been an issue so far using the re module.
Here is an example to get the uid of the calendar "Birthdays".
The main problem with my method is that I need to write wrapper functions for everything I want to access in applescript. A tiresome process.
The main advantage I see is a) it works and I get where I want and b) it seems future proof. For, if apple at some point discards applescript in favour of javascript or whatever, then all my programmes will still work once I adapted the wrapper modules.
Anyway ...
Hope that helps.
By the way, if anyone knows of a better way let me know. Or if someone does not know of a better way but likes my approach and would be interested in helping writing wrapper modules, let me know as well.
Here is the example.
Best,
Stephan
import subprocess
def asrun(ascript):
"Run the AppleScript ascript and return the standard output and error."
return subprocess.run(['osascript'],
input=ascript,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
encoding="utf-8")
def get_uid_of_calendar(name):
script = '''\
tell application "Calendar"
return uid of calendar "'''+name+'''"
end tell
'''
cal_res = asrun(script)
return cal_res.stdout
get_uid_of_calendar("Birthdays")
Per Python documentation, subprocess.call should be blocking and wait for the subprocess to complete. In this code I am trying to convert few xls files to a new format by calling Libreoffice on command line. I assumed that the call to subprocess call is blocking but seems like I need to add an artificial delay after each call otherwise I miss few files in the out directory.
what am I doing wrong? and why do I need the delay?
from subprocess import call
for i in range(0,len(sorted_files)):
args = ['libreoffice', '-headless', '-convert-to',
'xls', "%s/%s.xls" %(sorted_files[i]['filename'],sorted_files[i]['filename']), '-outdir', 'out']
call(args)
var = raw_input("Enter something: ") # if comment this line I dont get all the files in out directory
EDIT It might be hard to find the answer through the comments below. I used unoconv for document conversion which is blocking and easy to work with from an script.
It's possible likely that libreoffice is implemented as some sort of daemon/intermediary process. The "daemon" will (effectively1) parse the commandline and then farm the work off to some other process, possibly detaching them so that it can exit immediately. (based on the -invisible option in the documentation I suspect strongly that this is indeed the case you have).
If this is the case, then your subprocess.call does do what it is advertised to do -- It waits for the daemon to complete before moving on. However, it doesn't do what you want which is to wait for all of the work to be completed. The only option you have in that scenario is to look to see if the daemon has a -wait option or similar.
1It is likely that we don't have an actual daemon here, only something which behaves similarly. See comments by abernert
The problem is that the soffice command-line tool (which libreoffice is either just a link to, or a further wrapper around) is just a "controller" for the real program soffice.bin. It finds a running copy of soffice.bin and/or creates on, tells it to do some work, and then quits.
So, call is doing exactly the right thing: it waits for libreoffice to quit.
But you don't want to wait for libreoffice to quit, you want to wait for soffice.bin to finish doing the work that libreoffice asked it to do.
It looks like what you're trying to do isn't possible to do directly. But it's possible to do indirectly.
The docs say that headless mode:
… allows using the application without user interface.
This special mode can be used when the application is controlled by external clients via the API.
In other words, the app doesn't quit after running some UNO strings/doing some conversions/whatever else you specify on the command line, it sits around waiting for more UNO commands from outside, while the launcher just runs as soon as it sends the appropriate commands to the app.
You probably have to use that above-mentioned external control API (UNO) directly.
See Scripting LibreOffice for the basics (although there's more info there about internal scripting than external), and the API documentation for details and examples.
But there may be an even simpler answer: unoconv is a simple command-line tool written using the UNO API that does exactly what you want. It starts up LibreOffice if necessary, sends it some commands, waits for the results, and then quits. So if you just use unoconv instead of libreoffice, call is all you need.
Also notice that unoconv is written in Python, and is designed to be used as a module. If you just import it, you can write your own (simpler, and use-case-specific) code to replace the "Main entrance" code, and not use subprocess at all. (Or, of course, you can tear apart the module and use the relevant code yourself, or just use it as a very nice piece of sample code for using UNO from Python.)
Also, the unoconv page linked above lists a variety of other similar tools, some that work via UNO and some that don't, so if it doesn't work for you, try the others.
If nothing else works, you could consider, e.g., creating a sentinel file and using a filesystem watch, so at least you'll be able to detect exactly when it's finished its work, instead of having to guess at a timeout. But that's a real last-ditch workaround that you shouldn't even consider until eliminating all of the other options.
If libreoffice is being using an intermediary (daemon) as mentioned by #mgilson, then one solution is to find out what program it's invoking, and then directly invoke it yourself.
Is there a way to send some parameter from autohotkey to python.
Using Autohot key I read some number from the notepad and store in a variable and now I want to send this number to the python code in order to do some calculations.
My Autohotkey code is:
controlGetText, telphoneNumber, Edit1, Untitled - Notepad
And I want to send this telphoneNumber to python file.
Is there a way I can do that?
Do I need to create an exe file of a python and then call from autohotkey?
For example:
RunWait, C:\Button\button.exe telphoneNumber
Or do I need to run command prompt commands from autohotkey to run python program? Something like:
Run Cmd Python C:\Button\button.py telphoneNumber
I do not know which is the best way as I am newbie in Autohotkey.
Any suggestion will be appreciated.
EDIT:
However I succeded in sending parameter by using run command from autohotkey, which will execute the python file from command prompt.
Run Cmd \k "Python C:\Button\button.py %telphoneNumber%"
But still want to know if this is the right solution, or if there are others?
Inter-process communication would be capable of sending the information while the Python script is already running.
Forum thread: http://www.autohotkey.com/forum/topic21699.html (there's a nice documentation link in that post)
You could also use TCP/IP Network communication (like in the post below), but that probably wouldn't be quite as slick as using IPC.
Forum thread: http://www.autohotkey.com/forum/topic13829.html
The way you got it working is the easiest, and probably best, method of accomplishing what you want.
Communication between applications can be done with more methods then you probably can imagine, but as long as it doesn't have to be realtime you can call your programs with arguments, as it is easy and reliable.
Python COM server allows directly calling Python functions(with args and return) using AHK.
you use it like this: MsgBox % pythonComServer.method(args)
You do not need to have a python script already running.
ComObjCreate() will instantiate an instance of python.
I don't know how the inter-process communication is done in the background by pywin32, but using it is simple.
2 examples here: Call python function with arguments and get returned value in autohotkey
I like the python-send-buffer command, however I very often use Python embedded in applications, or launch Python via a custom package management system (to launch Python with certain dependencies).. In other words, I can't just run "python" and get a useful Python instance (something that python-send-buffer relies on)
What I would like to achieve is:
in any Python interpreter (or application that allows you to evaluate Python code), import a magic_emacs_python_server.py module (appending to sys.path as necessary)
In emacs, run magic-emacs-python-send-buffer
This would evaluate the buffer in the remote Python instance.
Seems like it should be pretty simple - the Python module listens on a socket, in a thread. It evaluates in the main thread, and returns the repr() of the result (or maybe captures the stdout/stderr, or maybe both). The emacs module would just send text to the socket, waits for a string in response, and displays it in a buffer.
Sounds so simple something like this must exist already... IPython has ipy_vimserver, but this is the wrong way around. There is also swank, while it seems very Lisp-specific, there is a Javascript backend which looks very like what I want... but searching finds almost nothing, other than some vague (possibly true) claims that SLIME doesn't work nicely with non-Lisp languages
In short:
Does a project exist to send code from an emacs buffer to an existing Python process?
If not, how would you recommend I write such a thing (not being very familiar with elisp) - SWANK? IPython's server code? Simple TCP server from scratch?
comint provides most of the infrastructure for stuff like this. There's a bunch of good examples, like this or this
It allows you to run a command, provides things comint-send-string to easily implement send-region type commands.
dbr/remoterepl on Github is a crude proof-of-concept of what I described in the question.
It lacks any kind of polish, but it mostly works - you import the replify.py module in the target interpreter, then evaluate the emacs-remote-repl.el after fixing the stupid hardcoded path to client.py
Doesn't shell-command give you what you are looking for? You could write a wrapper script or adjust the #! and sys.path appropriately.
Is it possible to use multiple languages along side with ruby. For example, I have my application code in Ruby on Rails. I would like to calculate the recommendations and I would like to use python for that. So essentially, python code would get the data and calculate all the stuff and probably get the data from DB, calculate and update the tables.Is it possible and what do you guys think about its adv/disadv
Thanks
If you are offloading work to an exterior process, you may want to make this a webservice (ajax, perhaps) of some sort so that you have some sort of consistent interface.
Otherwise, you could always execute the python script in a subshell through ruby, using stdin/stdout/argv, but this can get ugly quick.
Depending on your exact needs, you can either call out to an external process (using popen, system, etc) or you can setup another mini-web-server or something along those lines and have the rails server communicate with it over HTTP with a REST-style API (or whatever best suits your needs).
In your example, you have a ruby frontend website and then a number-crunching python backend service that builds up recommendation data for the ruby site. A fairly nice solution is to have the ruby site send a HTTP request to the python service when it needs data updating (with a payload of information to identify what it needs doing to what or some such) and then the python backend service can crunch away and update the table which presumably your ruby frontend will automatically pick up the changes of during the next request and display.
I would use the system command
as such
system("python myscript.py")
An easy, quick 'n' dirty solution in case you have python scripts and you want to execute them from inside rails, is this:
%x[shell commands or python path/of/pythonscript.py #{ruby variables to pass on the script}]
or
``shell commands or python path/of/pythonscript.py #{ruby variables to pass on the script}\ (with ` symbol in the beginning and the end).
Put the above inside a controller and it will execute.
For some reason, inside ruby on rails, system and exec commands didn't work for me (exec crashed my application and system doesn't do anything).