6

I need to load a third-party python script into memory and then execute it as as if it was on the command line, similar to how in PowerShell you can do iex(new-object net.webclient).downloadstring("http://<my ip>/myscript.ps1") then invoke it.

For example, I'd like to have my test.py on a web server then locally download and execute it in memory with command line switches, something like:

load("http://<ip>/test.py")
exec("test.py -arg1 value -arg2 value")

I appreciate this is quite naive but any help is appreciated, thanks!

15
  • 3
    By passing it to the python interpreter. python myscript.py? Commented Jan 11, 2019 at 22:27
  • 1
    Thanks, but I mean that I already have a running python process which will be downloading and executing the script, and I don't want the test.py script to touch the disk, I just want to run it in memory? Commented Jan 11, 2019 at 22:29
  • I mean in order to execute test.py from my python process I don't want to download it to disk and run exec("python test.py -arg1 value -arg2 value") , I need to achieve that without test.py being written out. If test.py does IO that's fine. Commented Jan 11, 2019 at 22:34
  • 1
    @roganjosh yeah, the simplest solution would be to save the file to disk and use subprocess to execute the file, this would handle the args etc. It's interesting to think about though... Commented Jan 11, 2019 at 22:43
  • 1
    @m0rv4i Two questions: 1. What is the reason that files cannot "touch" the hard drive? 2. If you have already identified a set of tools why can't you opt for a functional interface where the the input is the function's name and its arguments? Commented Jan 11, 2019 at 23:11

2 Answers 2

5

Here's a hacky way taking advantage of the -c option for the Python interpreter:

>>> import subprocess
>>> pycode = """
... import sys
... if sys.argv[1] == 'foo':
...     print('bar')
... else:
...     print('unrecognized arg')
... """
>>> result = subprocess.run(['python', '-c', pycode, 'bar'], stdout=subprocess.PIPE)
>>> print(result.stdout.decode())
unrecognized arg

>>> result = subprocess.run(['python', '-c', pycode, 'foo'], stdout=subprocess.PIPE)
>>> print(result.stdout.decode())
bar

This may come up with issues such as some platforms limiting the size of what you pass as arguments. I tried to do this using stdin, which the Python interpreter will accept, but then it won't accept arguments!

Sign up to request clarification or add additional context in comments.

Comments

4

I would recommend you to download the script by using requests, and then execute it with exec.

Something like this :

import requests
url="https://gist.githubusercontent.com/mosbth/b274bd08aab0ed0f9521/raw/52ed0bf390384f7253a37c88c1caf55886b83902/hello.py"
r=requests.get(url)
script=r.text
exec(script)

Sources :

Why is Python's eval() rejecting this multiline string, and how can I fix it?

https://www.programiz.com/python-programming/methods/built-in/exec

http://docs.python-requests.org/en/master/


If you want to specify arguments to the downloaded script you can do this :

import requests
import sys
sys.argv = ['arg1', 'arg2']
url="https://gist.githubusercontent.com/itzwam/90cda6e05d918034e75c651448e6469e/raw/0bb293fba68b692b0a3d2b61274f5a075a13f06d/blahblah.py"
script=requests.get(url).text
exec(script)

gist:

import sys

class Example(object):
    def run(self):
        for arg in sys.argv:
            print arg
if __name__ == '__main__':
    Example().run()

Sources :

https://stackoverflow.com/a/14905087/10902809

7 Comments

Thanks! This looks close, however if I understand correctly it's going to execute the script line by line, right? What I'm looking for is to execute it in a similar way to the command line so I can pass args and the __main__ method gets called etc...?
This will not work. This just executes the script in the current modules namespace as if it were text in that module. You want to be able to, say, pass arguments to the script, and have it act as if you did python myscript.py in the command line
you can easily specify arguments, but for the main method, i'm not sure PS: I tried it and it seems to call __main__
I edited my message and added an example on how to add arguments
But this requires clobbering your main script's namespace with this dynamically executed module's namespace, and hackily sharing sys.argv.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.