There are similar questions & answers to this kind of problem but I still can't find a satisfying answer to my specific problem:
I need to pass a variable (should be a global variable to this python script) to a python script from c++ code. I run this python script using following line in c++:
PyRun_SimpleString ( "exec(f.read())" );
and I want to pass this variable var="From c++" to the python environment so code in f script is able to access var variable.
I'm looking at PyDict_SetItem and PyDict_SetItemString, etc... but couldn't get it right. How can I do that?
Based on #mbostic 's comment, I did the following and it works:
add this line PyRun_SimpleString("var='From c++' ");
before this PyRun_SimpleString("exec(f.read())");.
This way f is able to access variable var.
Related
I'm facing some problems trying to load a full python script from my pastebin/github pages.
I followed this link, trying to convert the raw into a temp file and use it like a module: How to load a python script from a raw link (such as Pastebin)?
And this is my test (Using a really simple python script as raw, my main program is not so simple unfortunately): https://trinket.io/python/0e95ba50c8
When I run the script (that now is creating a temp file in the current directory of the .py file) I get this error:
PermissionError: [Errno 13] Permission denied: 'C:\\Users\\BOT\\Images\\tempxm4xpwpz.py'
Otherwise I also treid the exec() function... No better results unfortunately.
With this code:
import requests as rq
import urllib.request
def main():
code = "https://pastebin.com/raw/MJmYEKqh"
response = urllib.request.urlopen(code)
data = response.read()
exec(data)
I get this error:
File "<string>", line 10, in <module>
File "<string>", line 5, in hola
NameError: name 'printest' is not defined
Since my program is more complex compared to this simple test, I don't know how to proceed...
Basically What I want to achieve is to write the full script of my program on GitHub and connect it to a .exe so if I upgrade the raw also my program is updated. Avoiding to generate and share (only with my friends) a new .exe everytime...
Do you think is possible? If so.. what am I doing wrong?
PS: I'm also open to other possibilities to let my friends update the program without downloading everytime the .exe, as soon as they don't have to install anything (that's why I'm using .exe).
Disclaimer: it is really not a good idea to run an unverified (let alone untrusted) code. That being said if you really want to do it...
Probably the easiest and "least-dirty" way would be to run whole new process. This can be done directly in python. Something like this should work (inspiration from the answer you linked in your question):
import urllib.request
import tempfile
import subprocess
code = "https://pastebin.com/raw/MJmYEKqh"
response = urllib.request.urlopen(code)
data = response.read()
with tempfile.NamedTemporaryFile(suffix='.py') as source_code_file:
source_code_file.write(data)
source_code_file.flush()
subprocess.run(['python3', source_code_file.name])
You can also make your code with exec run correctly:
What may work:
exec(data, {}) -- All you need to do, is to supply {} as second argument (that is use exec(data, {})). Function exec may receive two additional optional arguments -- globals and locals. If you supply just one, it will use the same directory for locals. That is the code within the exec would behave like sort-of "clean" environment, at the top-level. Which is something you aim for.
exec(data, globals()) -- Second option is to supply the globals from your current scope. This will also work, though you probably has no need to give the execucted code access to your globals, given that that code will set-up everything inside anyway
What does not work:
exec(data, {}, {}) -- In this case the executed code will have two different dictionaries (albeit both empty) for locals and globals. As such it will behavie "as-in" (I'm not really sure about this part, but as I tested it, it seams as such) the function. Meaning that it will add the printest and hola functions to the local scope instead of global scope. Regardless, I expected it to work -- I expected it will just query the printest in the hola function from the local scope instead of global. However, for some reason the hola function in this case gets compiled in such a way it expects printest to be in global scope and not local, which is not there. I really did not figured out why. So this will result in the NameError
exec(data, globals(), locals()) -- This will provide access to the state from the caller function. Nevertheless, it will crash for the very same reason as in the previous case
exec(data) -- This is just a shorthand for exec(data, globals(), locals()
I'll want to know how to call a function in vs code. I read the answer to similar questions, but they don't work:
def userInput(n):
return n*n
userInput(5)
And appends nothing
def Input(n):
return n*n
And in the terminal:
from file import *
from: can't read /var/mail/file
Can somebody help me?
You are doing everything correctly in the first picture. In order to call a function in python on vs code you first have to define the function, which you did by typing def userInput(n):. If you want to see the result of your function, you should not use return, you should use print instead. Return is a keyword- so when your computer reaches the return keyword it attempts to send that value from one point in your code to another. If you want to see the result of your code, typing print (n) would work better.
Your code should look like this:
def userInput(n):
print (n * n)
userInput(5)
The code would print the result 25
Your terminal is your general way to access your operating system, so you have to tell it that you want it to interpret your Python code first.
If you want to run the file you're typing in, you have to first know the location of that file. When you type ls in your terminal, does the name of your Python file show up? If not, hover over the tab in VSCode (it's close to the top of the editor) and see what path appears. Then in your terminal type cd (short for "change directory") and then the path that you saw, minus the <your filename here>.py bit. Type ls again, and you should see your Python file. Now you can type python <your filename here>.py to run it (provided you have Python installed).
You could also run the IDLE by just typing python in your terminal. This will allow you to write your code line-by-line and immediately evaluate it, but it's easier to write in VSCode and then run it with the method I described before.
I did hours on research regarding the following question but I wasn't able to find an answer at all. Though there seem to be many fellows having problems with that. I hope I will recieve some help from the community. ;)
I have a Cshell script where I need to call a Python3 script from. Also I am passing a variable.
.csh
#!/bin/csh -f
set variable = value
/../geos.py $variable
So far so fine. In my Python3 script I take this variable, do some calculations and now want to pass back the 'new_variable' to the VERY SAME C shell script in order to proceed my set of data.
.py
import os
...
new_variable = 'foobar'
os.environ['new_variable'] = new_variable
return new_variable
My actual goal is that my C Shell script:
#!/bin/csh -f
set variable = value
/../geos.py $variable
echo $new_variable
doesn't return 'Undefined variable'. So obviously my code doesn't work. Sure, I might be able to temporarily save the python calculations into a file but this seems quite unconvincingly. Also, I understand that it is just not possible to manipulate an environmental variable of the shell through a child process, but still I only want to pass a normal variable. There should be one way, no?
If it is possible, I wasn't able to figure out any solution using subprocess.check_call. What am I missing?
E D I T:
Merci beaucoup.
I knew that there must have been an easy solution. Thanks a lot!
For CSHELL the following code worked:
set new_variable=`../geos.py $variable`
echo $new_variable
For BASH the following code worked:
new_variable=`../geos.py $variable`
echo $new_variable
In the python script itself you don't need to do anything but putting your desired variable into standard output, e.g. print(you_even_can_name_them_as_you_want). No os.environ oo whatever necessary. Made my day. SOLVED
in bash I'd use:
new_variable=$(../geos.py $variable)
Have the python script produce the new value as standard out (i.e. print(new_variable) )
In csh I don't know, maybe you would have to use backquotes instead of $() ?
How do I execute all the code inside a python file so I can use def's in my current code? I have about 100 scripts that were all written like the script below.
For a simple example, I have a python file called:
D:/bt_test.py
His code looks like this:
def bt_test():
test = 2;
test += addFive(test)
return(test)
def addFive(test):
return(test+5)
Now, I want to from a completely new file, run bt_test()
I've tried doing this:
def openPyFile(script):
execfile(script)
openPyFile('D:/bt_test.py')
bt_test()
But this doesn't work.
I've tried doing this as well:
sys.path.append('D:/')
def openPyFile(script):
name = script.split('/')[-1].split('.')[0]
command = 'from ' + name + ' import *'
exec command
openPyFile('D:/bt_test.py')
bt_test()
Does anyone know why this isn't working?
Here's a link to a quicktime video that will help explain what's happening.
https://dl.dropbox.com/u/1612489/pythonHelp.mp4
You should put those files somewhere on your Python path, and then import them. That's what the import statement is for. BTW: the same directory as your main program is on the Python path, that could be a good place to put them.
# Find and execute bt_test.py, and make a module object of it.
import bt_test
# Use the bt_test function in the bt_test module.
bt_test.bt_test()
The reason that execfile doesn't work is because the functions inside bt_test are limited by the scope of the openPyFile function. One simple test would be to try to run bt_test() from inside openPyFile. Since openPyFile doesn't really do anything other than execfile you could get rid of it altogether, or you could alias execfile
openPyFile=execfile
Note putting the file in your python path and importing it is definitely your best bet -- I only post this answer here to hopefully point out why you're not seeing what you want to see.
In addition to Ned's answer, __import__() might be useful if you don't want the file names hardcoded.
http://docs.python.org/library/functions.html#__import__
Update based on the video.
I don't have access to Maya, but i can try and speculate.
cmds.button(l='print', c='bt_press()') is where the issue seems to lurk. bt_press() is passed as a string object, and whatever way the interpreter uses to resolve that identifier doesn't look in the right namespace.
1) Try passing bt_press() with the module prepended: cmds.button(l='print', c='bt_test.bt_press()')
2) See if you can bind c directly to the function object: cmds.button(l='print', c=bt_press)
Good luck.
>>> from bt_test import bt_test
>>> bt_test()
I have a scenario where i want to dynamically generate a python script - inside my main python script - store it as a string and then when need be, execute this dynamically generated script from my main script.
Is this possible, if so how?
thanks
For a script in a file use exec
For a script in a string use eval
!!! But !!!
before you use strings passed in from an external source, sanity check them!
Otherwise you expose the ability to execute arbitrary code from
within you program,
so range check your variables!
You do not ever want to be asking the question:
"excuse me mam, did you really name your son Robert'); DROP TABLE students; -- "?
If you dont understand the reference - see this quick cartoon...
http://xkcd.com/327/
but when you EVAL - you are taking full responsibility for the instructions that you are eval'ing.
Read up on the execfile() function.
http://docs.python.org/library/functions.html?highlight=exec#execfile
May want to look at the statement exec: http://docs.python.org/release/2.5.2/ref/exec.html
If you want to execute the script within the context of the main script, you might want to check eval [ http://docs.python.org/py3k/library/functions.html#eval ]
Not sure how wise this is but isn't the exec function what you use if you need to execute Python code?
There is precedence for what you are trying to do. The collections.namedtuple function builds a template string which is passed to exec in order to build a dynamically defined class.
As of Python version 3.11, execfile (which was the most convenient function) is not listed as built-in function anymore.
#George Lambert answer is the way to go. I'll add just some code for quick reference.
Run script within script
To run the script "run_me.py" within the script "main.py" do this:
run_me.py be like
print("hello_world")
main.py be like
with open("run_me.py", "r") as fl:
exec(fl.read())
Run code contained in a string
To run the code contained in a string us eval:
main.py be like
string_w_py_code = "print('hello world')"
eval(string_w_py_code)