Is there an R equivalent of the pythonic "if __name__ == "__main__": main()"? - python

The objective is to have two simple ways to source some code, say func.R, containing a function. Calling R CMD BATCH func.R initializes the function and evaluates is. Within a session, issuing source("func.R") simply initializes the function.
Any idea?

I think that the interactive() function might work.
This function returns TRUE when R is being used interactively and FALSE otherwise. So just use if (interactive())
i.e. the equivalent is
if (!interactive()) {
main()
}

Another option is:
#!/usr/bin/Rscript
# runs only when script is run by itself
if (sys.nframe() == 0){
# ... do main stuff
}

You could pass arguments into R, and if an argument is present run main(). More on arguments here: http://yangfeng.wordpress.com/2009/09/03/including-arguments-in-r-cmd-batch-mode/

It's a lot of work, but I finally got it (and posted at Rosetta Code).
This example exports a function called meaningOfLife. When the script is run by itself, it runs main. When imported by another R file, it does not run main.
#!/usr/bin/Rscript
meaningOfLife <- function() {
42
}
main <- function(program, args) {
cat("Main: The meaning of life is", meaningOfLife(), "\n")
}
getProgram <- function(args) {
sub("--file=", "", args[grep("--file=", args)])
}
args <- commandArgs(trailingOnly = FALSE)
program <- getProgram(args)
if (length(program) > 0 && length(grep("scriptedmain", program)) > 0) {
main(program, args)
q("no")
}

I asked a similar question, in an answer, Matthew Plourde suggested using getOption('run.main', default=TRUE) in the main script and then setting options(run.main=FALSE) before calling source(). This worked in my case.
Otherwise a simpler pattern when you have an R script creating a bunch of functions and you want to write a few lines at the end of the script to experiment with the use of a function: place these extra lines in an if(FALSE){} block.

This works fairly well for my use. If you have two files and want to source one with the other while only running a certain part of the file.
parent file: parent.R
print("Running Parent File")
`__name__` <- "__main__"
print(paste0("This file is : ", `__name__`))
`__src__` <- "__not.main__"
source("child.R")
rm(`__src__`)
child file: child.R
print("Running Child File")
`__name__` <- "__main__"
if (exists("__src__")){`__name__` <- `__src__`}
if (`__name__` == "__main__"){
print(paste0("This file is : ", `__name__`))
} else {
print(paste0("This file is : ", `__name__`))
}
Output when running Rscript parent.R
[1] "Running Parent File"
[1] "This file is : __main__"
[1] "Running Child File"
[1] "This file is : __not.main__"
Output when running Rscript child.R
[1] "Running Child File"
[1] "This file is : __main__"
A more robust method would be to write a custom source function where a list of arguments can be included.
source2 <- function(file, args = list()){
tryCatch(
expr = {
assign("__src__", "__not.main__", envir = globalenv())
assign("__src.args__", args, envir = globalenv())
source(file)
},
error = function(e){
message("File could not be sourced")
},
finally = {
rm(list = c("__src__", "__src.args__"), envir = globalenv());
assign("__name__", "__main__", envir = globalenv())
})
}
source2("child.R", args = list("list", "of", "arguments"))

Related

Call Boost Python functions from simple python classes/functions

I have classes defined in C++ code, and added to the python dictionary like this:
try
{
Py_Initialize();
}
catch (bp::error_already_set &)
{
parse_python_exception();
}
main_module = bp::import("__main__");
main_namespace = main_module.attr("__dict__");
bp::class_<Gamefunctions> gamefunctions_binding = bp::class_<Gamefunctions>("Gamefunctions");
m_localDictionary["Gamefunctions"] = gamefunctions_binding;
m_localDictionary["gamefunctions"] = bp::ptr(&gamefunctions);
void (Gamefunctions::*addlog_comp)(string, string, string, bool) = &Gamefunctions::addlog;
void (Gamefunctions::*addlog_simp)(string, bool) = &Gamefunctions::addlog;
gamefunctions_binding.def("addlog", addlog_comp);
gamefunctions_binding.def("addlog", addlog_simp);
Py_Initialize();
bp::object execute;
string testcode = "def calllog():\n";
testcode += " gamefunctions.addlog(\"logmessage\", True)\n";
testcode += "gamefunctions.addlog(\"logmessage\", True)\n";
testcode += "calllog()";
try
{
execute = exec((testcode).c_str(), main_namespace, m_localDictionary);
}
catch (bp::error_already_set &)
{
parse_python_exception();
}
And I tried to call it from a function in a python file like this:
def calllog():
gamefunctions.addlog("logmessage",True)//not found
gamefunctions.addlog("logmessage",True)//works fine
calllog()
The call from outside the "def" works perfectly, but when I call it from the "def" It gives me this error message:
<type 'exceptions.NameError'> global name 'gamefunctions' is not
defined
How can I "define" the 'gamefunction' class in the 'calllog()' function?
Sorry for my bad english and thank you for any advice you give.
After a long searching, I found this page here:
Boost Python - Global and Local dictionary
I already knew, there is something with the local and global scopes, but I approached the probmem from the wrong direction.
I tought, I need to link the inside classes somehow in the python function/class itself, but actually I need to add the C++ classes to the global dictionary too like this:
bp::class_<Gamefunctions> gamefunctions_binding = bp::class_<Gamefunctions>("Gamefunctions");
m_localDictionary["Gamefunctions"] = gamefunctions_binding;
m_localDictionary["gamefunctions"] = bp::ptr(&gamefunctions);
main_namespace["Gamefunctions"] = gamefunctions_binding;
main_namespace["gamefunctions"] = bp::ptr(&gamefunctions);
void (Gamefunctions::*addlog_comp)(string, string, string, bool) = &Gamefunctions::addlog;
void (Gamefunctions::*addlog_simp)(string, bool) = &Gamefunctions::addlog;
gamefunctions_binding.def("addlog", addlog_comp);
gamefunctions_binding.def("addlog", addlog_simp);

Pass function and arguments from node to python, using child_process

I am new to child_process and I want to experiment with its capabilities.
Is there any way to pass a function and arguments to a python file, using spawn (or exec or execFile is spawn cannot do it)?
I want to do something like (pseudocode)
spawnORexecORexefile (python path/to/python/file function [argument1, argument2] )
or maybe
spawnORexecORexefile (python path/to/python/file function(argument1, argument2) )
Please explain and maybe give an example, because I am a newbie
How I am doing it now?
in node
var process = spawn('python', [path/to/pythonFile.py, 50, 60] );
in pythonFile.py
import sys
import awesomeFile
hoodie = int(sys.argv[1])
shoe = int(sys.argv[2])
awesomeFile.doYourMagic().anotherThing(hoodie, shoe)
as you can see, from node, I send data to pythonFile and then to awesomeFile, to a specific function
I would like to "cut the middle man" and remove the pythonFile and send data from node directly to the awesomeFile file, to a specific function. This is why I am asking
Thanks
You can run a specific Python function from the command-line using the form python -c 'import foo; print foo.hello()' (from https://stackoverflow.com/a/3987113/5666087).
Place both the files below in the same directory, and run with node index.js. You should see the following output:
Hoodie: 10
Shoe: 15
awesomeFile.py
def myfunc(hoodie, shoe):
hoodie = int(hoodie)
shoe = int(shoe)
print("Hoodie:", hoodie)
print("Shoe:", shoe)
index.js
const { spawn } = require('child_process');
let hoodie = 10,
shoe = 15;
const result = spawn("python",
["-c", `import awesomeFile; awesomeFile.myfunc(${hoodie}, ${shoe})`])
result.stdout.pipe(process.stdout)
You can group all the relevant functions you want to call to class and make a dictionary out of a class that maps to the class function. You can directly call awesome.py without an intermediate index.py. You can extend the class AwesomeFile with your methods
The follow program will take user input -
which python file to run
which method to run
method arguments
Number of arguments mismatch
What if unknown methods are given
awesomeFile.py
import sys
class AwesomeFile:
def __init__(self):
pass
def doYourMagic(self):
return self
def anotherThing(self, hoodie, shoe):
print(int(hoodie))
print(int(shoe))
awesomeFile = AwesomeFile()
methods = {m:getattr(awesomeFile, m) for m in dir(AwesomeFile) if not m.startswith('__')}
def run():
method_name = sys.argv[1]
if method_name not in methods:
print(f"Unknown Method {method_name}")
return
methodArgCount = methods[method_name].__code__.co_argcount
if methodArgCount - 1 != len(sys.argv[2:]):
print(f"Method {method_name} takes {methodArgCount - 1} arguments but you have given {len(sys.argv[2:])}")
return
methods[method_name](*sys.argv[2:])
if __name__ == "__main__":
run()
index.js
Note** - You would to install prompt - npm i prompt
'use strict';
var prompt = require('prompt');
const { spawn } = require( 'child_process' );
var prompt_attributes = [
{
name: 'pythonFilePath'
},
{
name: 'cmdLineArgs'
}
];
prompt.start();
prompt.get(prompt_attributes, function (err, result) {
if (err) {
console.log(err);
return 1;
}else {
console.log('Command-line received data:');
var filePath = result.pythonFilePath;
var cmdLineArgs = result.cmdLineArgs;
var args = cmdLineArgs.split(" ");
args.unshift(filePath);
const pythonProgram = spawn( 'python' , args);
pythonProgram.stdout.on( 'data', data => {
console.log( `stdout:\n\n ${data}` );
} );
pythonProgram.stderr.on( 'data', data => {
console.log( `stderr: ${data.data}` );
} );
pythonProgram.on( 'close', code => {
console.log( `child process exited with code ${code}` );
} );
}
});
To run the program -
I/O:
Argument Mistmatch -
prompt: Python File Path. Give absolute or relative path: ../python_files/awesomeFile.py # python file can be any location in the system
prompt: Command Line Arguments. Format = func_name arguments_list (Ex addFunc 1 2): anotherThing 1
Command-line received data:
stdout:
Method anotherThing takes 2 arguments but you have given 1
child process exited with code 0
Function Not found
prompt: Python File Path. Give absolute or relative path: ../python_files/awesomeFile.py
prompt: Command Line Arguments. Format = func_name arguments_list (Ex addFunc 1 2): helloworld 1 2
Command-line received data:
stdout:
Unknown Method helloworld
child process exited with code 0
Success Case:
prompt: Python File Path. Give absolute or relative path: ../python_files/awesomeFile.py
prompt: Command Line Arguments. Format = func_name arguments_list (Ex addFunc 1 2): anotherThing 50 60
Command-line received data:
stdout:
50
60
child process exited with code 0

What does followObject_Setup and followObjectExpr meant to do here

I am new to Maya scripting and I am asked to convert the below MEL to Python.
I've been searching for all the commands in Mel and everything seemed to be fine, except the two terms ## followObject_setup and followObjectExpr ## in the below script.
Can someone explain me, what is this.
Thanks in Advance
global proc newPointBlast_Follow()
{
/*
Function to get the point from selection and camera from view.
Attach the camera to point.
*/
global string $followingCamera[];
global string $object_to_Follow[];
undoInfo -swf off;
string $currentPanel = `getPanel -wf`;
string $type = `getPanel -typeOf $currentPanel`;
if ( $type == "modelPanel" )
{
$followingCamera[0] = `modelPanel -q -camera $currentPanel`;
}
$object_to_Follow = `ls -sl`;
if ( `size( $object_to_Follow )` == 0 )
{
confirmDialog -title "No Object selected" -message "Please select an Object or Vertex to Follow" -button "OK"; }
else
{
newPointBlast_unlockImagePlanes();
if ( `objExists followObject_setup` )
{
delete followObject_setup;
}
if ( `objExists followObjectExpr` )
{
delete followObjectExpr;
}
What is the meaning of the last if statements?
It is some variables that has been defined somewhere else.
In maya, if you type in MEL :
whatIs followObjectExpr
whatIs followObject_setup
if it return None, it is not a proc or something belonging to maya
otherwise if you cant to convert your commands roughly in python, you can use the command below to convert a mel string :
import pymel.tools.mel2py as mel2py
text = raw_input()
print(mel2py.mel2pyStr(text, pymelNamespace='pm'))
or you can use this to convert a mel file :
import pymel.tools.mel2py as mel2py
mel2py.mel2py('/path/maya20XX/scripts/others/doWrapArgList.mel',
'/path/myfolder/doWrapArgList/')

Python dict to select function runs all of them

So I tried cutting down on nested if's by using a dict to select a function to run. When calling execute in a test I'm usually calling it with "execute("BACKUP","/home/src","/home/dest")"
But for some reason it runs both the BACKUP option twice. What am I doing wrong? I'm using Python3
def execute(jobtype, src, dst):
if jobtype == "FULL":
_o_src = fs.Index(src)
fs.MakeFolders(_o_src.GetFolders(), dst)
fs.MakeFiles(src, dst, _o_src.GetFiles())
if jobtype == "INCREMENTAL":
print("DO INCREMENTAL BACKUP " + src + " TO " + dst)
# Do the things
options = {
"BACKUP": execute(self.jobtype, self.src, self.dst),
"RESTORE": execute(self.jobtype, self.dst, self.src),
}
options[jobtype]()
You're not storing your execute function in your options dict. You're storing the result of calling that function. And since it's the same function either way with different parameters being passed in, you don't actually need the function to be the values in your dict. You need the parameters. Change your last four lines to:
options = {
"BACKUP": [self.jobtype, self.src, self.dst],
"RESTORE": [self.jobtype, self.dst, self.src],
}
execute(*options[jobtype])

compare program results on cpp and python

I would like to test cpp code using Python.
I have next code and a.exe file, which I get after complilation:
int main() {
std::istream& input_stream = std::cin;
std::ostream& output_stream = std::cout;
Data input_data = ReadData(input_stream);
Data output_data = DoSomethingWithData(input_data);
OutputData(output_data, output_stream);
return 0;
}
And I have py code:
input_data = ''
for line in sys.stdin:
input_data += line
output_data = do_something_with_data(input_data)
print(output_data)
I would like to make py script, which can give equal input to cpp programm and py programm and compare outputs. Is there an easy way to do it?
You can use subprocess (https://docs.python.org/2/library/subprocess.html):
input_data = "some-data"
cpp_output = subprocess.check_output(["a.exe", input_data])
python_output = subprocess.check_output(["python", "test.py", input_data])
assert cpp_output == python_output
It looks like you are using windows. I would redirect the output of both programs to a file and then compare files. In cmd.exe:
a.exe > a_output.txt
your_python_script.py > py_output.txt
FC a_output.txt py_output.txt
You can use ">" to redirect output to text. The command FC (File Compare) checks the differences between the files.

Categories

Resources