Can Not execute Python .py file using RobotFramework like Javascript - python

Has anyone found a method for executing their .py files from the Robot Framework like you can for JS?
RobotFramework:
Executes the given JavaScript code.
code may contain multiple statements and the return value of last
statement is returned by this keyword.
code may be divided into multiple cells in the test data. In that
case, the parts are catenated together without adding spaces.
If code is an absolute path to an existing file, the JavaScript to
execute will be read from that file. Forward slashes work as a path
separator on all operating systems. The functionality to read the code
from a file was added in SeleniumLibrary 2.5.
Note that, by default, the code will be executed in the context of the
Selenium object itself, so this will refer to the Selenium object. Use
window to refer to the window of your application, e.g.
window.document.getElementById('foo').
Example: Execute JavaScript window.my_js_function('arg1', 'arg2')
Execute JavaScript ${CURDIR}/js_to_execute.js
It's bs that I can't run my .py files this way...

The Execute Javascript extension isn't a part of RobotFramework, it's something added by the Selenium integration, it would therefore follow that you can't use Selenium to execute a .py file.
That said, RobotFramework is written in Python and can obviously be extended with a Python script.
Can you clear up what you're actually trying to achieve here though?
My concern is that if you're using a .py file in your test state to validate your code, isn't that introducing an uncertainty that means that what you're testing is not the same as the code that gets executed when you release your project?
A bit more detail would help a lot here!

Related

Python command to execute non-Python (MQL5) files?

I have a collection of expert advisor (EA) scripts written in the MQL5 programming language for the stock/forex trading platform, MetaTrader5. The extension of these files is mq5. I am looking for a way to programatically run these MQL5 files from my Python script on a regular basis. The EAs do some price transformations, eventually saving a set of csv files that will later be read by my Python script to apply Machine Learning models on them.
My first natural choice was the Python API for MetaTrader5. However, according to its documentation, it "is designed for convenient and fast obtaining of exchange data via interprocessor communication directly from the MetaTrader 5 terminal" and as such, it doesn't provide the functionality I need to be able to run MQL scripts using Python.
I have found some posts here on SO (such as #1, #2) about executing non-python files using Python but those posts seemed to always come with the precondition that they already had Python code written in them, only the extension differed - this is different from my goal.
I then came across Python's subprocess module and started experimenting with that.
print(os.path.isfile(os.path.join("path/to/dir","RSIcalc.mq5")))
with open(os.path.join("path/to/dir","RSIcalc.mq5")) as f:
subprocess.run([r"C:\Program Files\MetaTrader 5\terminal64.exe", f], capture_output=True)
The print statement returns True, so the mq5 file exists in the specified location. Then the code opens the MetaTrader5 terminal but nothing else happens, the EA doesn't get executed, process finishes immediately after that.
Am I even on the right track for what I'm trying to achieve here? If yes, what might be the solution for me to run these MQL5 scripts programatically from Python?
Edit:
I use Windows 10 64-bit.
subprocess is indeed the right module for what you want to achieve. But let's look at what you're doing here:
with open(os.path.join("path/to/dir","RSIcalc.mq5")) as f
You're creating a file descriptor handle called f, which is used to write or read contents from a file. If you do print(f) you'll see that it's a python object, that converted to string looks like <_io.TextIOWrapper name='RSIcalc.mq5' mode='r' encoding='UTF-8'>. It is extremely unlikely that such a string is what you want to pass as a command-line parameter to your terminal executable, which is what happens when you include it in your call to subprocess.run().
What you likely want to do is this:
full_path = os.path.abspath(os.path.join("path/to/dir","RSIcalc.mq5"))
result = subprocess.run([r"C:\Program Files\MetaTrader 5\terminal64.exe", full_path], capture_output=True)
Now, this assumes your terminal64 can execute arbitrary scripts passed as parameters. This may or may not be true - you might need extra parameters like "-f" before passing the file path, or you might have to feed script contents through the stdin pipe (unlikely, on Windows, but who knows). That's for you to figure out, but my code above should probably be your starting point.
I don’t think you need to be passing a file object to your sub process statement. In my experience. A program will run a file when the path to the file is provided as a command line argument. Try this:
subprocess.run([r"C:\\Program Files\\MetaTrader 5\\terminal64.exe", os.path.join(“path/to/dir”, “RSIcalc.mq5”], capture_output=True)
This is the same as typing C:\Program Files\MetaTrader 5\terminal64.exe path\to\dir\RSIcalc.mq5 in your terminal.

Running python code from a text file into your python program

I Want to save my python code as a text file then make a python launcher that once you log in the program starts executing code from the text file. Is This possible to do and if so can someone please help
The request is a bit obscure but if I got it right you want create a python script that is able to launch other python scripts.
I do not understand the use of this but here's a possible solution, keeping in mind that your "text file" was saved as "yourscript.py":
from subprocess import call
call(["python", "yourscript.py"])
This code will act like if you'd run the saved "yourscript.py" from the command line.
Consider using runpy, e.g.:
import runpy
runpy.run_path("yourscript.py", init_globals={'global_name':some_value})
With optional init_globals parameter you can control global objects within the runtime of the script you are calling.

Dynamically read value of html input field: python

I have an external browser plugin (which is blackbox to me). This plugin tries to fill values to input fields of html page (on load. I want to make a program, which is able if the external program filled values properly.
So what I want to do is to open an url from my python program in a browser. On load of this page is automatically executed the plugin and tries to insert values. After that I want to find specific input fields and resolve, whether they are filled correctly or not in the current instance of the browser and page.
Is there any way to do such thing using python (standard or 3rd party) modules? Could you recommend me any?
(Note: I also want to build exe file using cx_freeze, so the best would be, if the module does not depend on external files)
Thanks.
I would suggest using PyQt or Selenium.

Dynamically running python code on google app engine

I am trying to be able to dynamically run python code, with variables being able to be passed through to the code. I was able to do this on my computer before I added my project to the google app engine environment (because I can access all the files, but now, with google app engine, I can not do that.
I am struggling to find a solution to this problem. It does not need to be too terribly fancy, just send variables in and get html out, as well as scripts being able to be added client side (the crucial part) to whatever database method that is used.
Edit:
well basically what I mean by dynamically is so that I can import (or thats what I did in IDLE when I tested the prototype, the solution will probably not be called importing) a python script with the name of the library being stored in a variable, as well as an unknown number of variables that would be added. I got this to work on Idle, but now I need to get it to work in the google app engine environment, and people need to be able to upload scripts as well (which is the main problem that cascades into many more problems)
Edit:
When I say that I managed to get this to work on my local machine, I mean I was able to manually drop scripts into the same directory as my main script. The script would later import and execute the scripts when necessary. I was able to get this to work with the following code:
#calling function
mod = __import__('actions.'+folder+'.'+FILE)
VAR = getattr(getattr(mod, folder), FILE)
response = VAR.Main()
print response
This code worked on both my laptop and in the google app engine environment, But When I try to add more scripts to the directory is when things get problematic. On my laptop I could just move the file over one way or another because I had full access to the file directory. On Google App engine I do not have the ability to just upload a file to the same directory or subdirectory of the rest of my python scripts. So basically the problem comes up when trying to design a way to allow more code to come into the system (in my case, adding more 'plugins').
The answer is the exec statement (also known as the exec() function) or the eval() function. See http://docs.python.org/reference/simple_stmts.html#the-exec-statement and http://docs.python.org/library/functions.html?highlight=eval#eval. These can execute arbitrary Python code from a string. exec() runs a script and you get the side effects; eval() takes an expression and returns its value. Typically you pass input in as variables in the local namespace.
Ok, So what I eventually did was use the datastore to upload everything such as the name, description, uploader and code of the plugin (for now the code is just entered into a textarea box). I then, instead of importing a file located in a folder under the same directory of my code like I had before when running everything off of my desktop, Imported the plaintext code into a module using this little bit of magic:
#Initiating Variables for use by importing functions
module_name = 'mymod'
filename = 'action_file'
source = PossibleMatches[0][1] #the source code from the best matched option
# define module_name somewhere
import types
module = types.ModuleType(module_name)
# source should the code to execute
# filename should be a pseudo-filename that the code's from
# (it doesn't actually have to exist; it's used for error messages)
code_object = compile(source, filename, 'exec')
#execute the code in the context of the module
exec code_object in module.__dict__
#Executing the 'Main' Function from the code
return module.Main()

Web interface to a Python script, with "streaming text"

I have a Python command-line script that can take some time to run (from 5 seconds to 5 minutes), depending on the checks it does. The script uses many command-line arguments, some mandatory, most optional.
I'd like to "webify" this script, making it possible to access it from a Web browser, but without changing the core python script, so by launching it from something else (like another Python script for instance)
I've used mod_python with Apache before so it's not too much of a problem to build a Python script that generates a Web page with a form and a Submit button and run my core python script from it.
The problem is with the output of the core python script. I don't want to wait until it has completed to display its output in a DIV (or in a FRAME). As soon as it generates a line, I want that line to be displayed on the Web interface, a kind of text streaming in the DIV.
I know how to do this from a Javascript contained in a HTML page or as an external Javascript file, but not from the output of another program.
Any idea how I can achieve this? I prefer to keep it all Python+Apache but if something else is really required (PHP, AJAX, Javascript, ...), I can live with it.
As suggested by whatnick below, I tried to redirect the output of the core python script in a temporary file and display this file using the AJAX Logfile Trailer & Viewer code I found on the Web.
It sort of works but there is still some buffering, as the lines appear in the "log tail page" in several chunks of lines, not lines by lines. This is most probably due to the fact the AJAX script reloads the log file using a timer, every X milliseconds (configurable in the script, used for a Javascript timer). Even if I lower it, it still not fast enough for my core script, which can sometimes output several lines very fast.
You can log the output from your lengthy script to a file and use a javascript timer based code to pull, parse and display content of the log periodically. If pulling the entire log is too much, you can also delegate to a smaller/faster server side python script to parse the log and pass on the tail of the log to the calling javascript. This is how router logs etc. in embedded devices is displayed.
Good luck. Here is a small tutorial on Javascript Timers.
For IE and Firefox, if you stream your response, it will start rendering before the full page is provided. You can thus stream a log of what is going on in the middle of an HTML file. Once the process is completed, you render the rest of the page as normal.
You will have to go through some convolutions to get a normal Python template engine to work with that since they tend to do everything in one shot.
Chrome does not seem to like this very well (I expect that is a webkit thing so you can probably discount Safari from this trick as well) and I am not sure about Opera.

Categories