1

I want to keep a piece of code in a txt file and execute it from my Python script.

For example in the txt file there is

print("ok")

I want my programme to print ok and not print print("ok "). How can I do this?

frlan
  • 6,950
  • 3
  • 31
  • 72
luka
  • 55
  • 1
  • 1
  • 2
  • 2
    You almost never want to do this but if you do, lookup exec. Horrible thing. *shudders* – muddyfish Jul 29 '15 at 15:34
  • https://docs.python.org/2/library/functions.html#execfile – xrisk Jul 29 '15 at 15:38
  • Keep in mind that this is a grave security risk. Imagine what would happen if your file contained malicious code! – xrisk Jul 29 '15 at 15:39
  • I want to create a level editor for a game but this is the only way i think of, i need to stack data in an other file and then use it – luka Jul 29 '15 at 15:48
  • 1
    I'd suggest you use some sort of structured text file for this. XML might be a good choice here. So you will store your game level information in xml file and use it in your game. – konart Jul 29 '15 at 15:51
  • Ok eval fonction works for print but when when i want to declare variables like a =4 I have a syntaxe error is there anyway to set new variables,class instance from a text file ? – luka Jul 29 '15 at 17:01
  • I certainly wouldn't use XML to save such simple data as monsters. It can become pain in the ass pretty quickly. Use key=value file if you want it to be text and not a pickle. – Dalen Jul 30 '15 at 12:02

3 Answers3

3

Doing what you want usually is a security risk, but not necessarily so.

You'll definitely have to notify the user about potential risk.

There is more than one program using execfile() or compile() and exec statement to provide plug-ins system.

There is nothing so ugly about it, you just have to know what are you doing, when and where.

Both execfile(), eval() and exec statement allow you to specify a scope in which will your code be executed/evaluated.

myscope = {}
execfile("myfile.txt", myscope)

This will prevent the new code being mixed with the old one. All variables classes, functions and modules from myfile.txt will be contained in myscope dictionary.

This, however, does not prevent malicious code to delete all files it can from your disk or something similar.

Python 2 has a nice module called rexec, but from Python 2.2 it doesn't work any more.

It implements execfile() exec statement and eval() in restricted environment. Though it doesn't work it is there, and you can dig through the code to see how it is done.

So, you see, it is possible to allow only secure code to execute (well, as secure as it can be) from external source.

There is another way too. You can load the file, compile the code from it and then inspect it to see what it does. Then say, yes I'll execute it or no, I won't. This is, however, a little bit more work and a lot of complications.

But, I don't think that it'll be necessary to go through all that stuff. Please elaborate some more on your problem. What exactly do you mean by level editor? I don't think external code is a solution for that.

Dalen
  • 4,128
  • 1
  • 17
  • 35
  • Ok so my game is a spaceship that can shoot monsters basically so a level editor is for the user to simply create a level ( chose the type of monsters when it spawn chose the background etc ..) for exemple to create a monster its 5lines of code so when the user press new monster button it will automatically write those 5lines with his parameters in the txt file. That is my plan for now if you have an other idea please tell me – luka Jul 29 '15 at 17:38
  • You have a monster represented as an object I take it. If it is so then it is trivial to change it's attributes to reflect what you want. You can have more monster types defined and at the runtime do something like: 'newmonster = object(); newmonster.speed = 50; for x in dir(crocodile): setattr(newmonster, x, getattr(crocodile, x))'. In this way you will make new crocodile with speed 50. You can of course automatize it all by cleverly designed inheritance. – Dalen Jul 29 '15 at 22:47
  • To save it all, you can use configparser module to save only chosen attributes values as an INI file, or design some file of your own, or use pickle/cPickle module to save them as 'import cPickle as pickle; f = open("newmonster.txt", "wb"); pickle.dump(newmonster, f); f.close()' Loading will be done using pickle.load(), but to do it with dynamically filled objects will be a bit tricky. But it'll work. – Dalen Jul 29 '15 at 22:48
  • 1
    ok execfile fonction doesnt exist in python 3.0 and more you have to use exec(open("file.txt").read()) – luka Jul 30 '15 at 09:13
  • Yes and no. It is possible to jam in more than one pickle in the file then parse it manually to separate them. Use pickle.dumps() and pickle.loads() instead of writing/loading directly to/from file. But it is easier to put all your objects into a dictionary or list and pickle it. Then when unpickling you just unpack that dict. It'll work flawlessly. – Dalen Jul 30 '15 at 09:13
  • It probably does exist still, but it is pushed in some module instead being in __builtins__. It is done for some other "old" functions. Look around for it, or do as you wrote. – Dalen Jul 30 '15 at 11:55
  • However, it'll be a good idea to load the code at the beginning and execute it later. In this case I'd advise compiling it and storing the compiled code object somewhere, then calling exec on it when you need it later. It'll speed things up at runtime. 'monster = compile("\n".join(open("newmonster.txt", "rb").readlines()), "newmonster.py", "exec"); monsterscope = {}; exec(monster, monsterscope)' NOTE: compile() doesn't like messed newlines (Python's 2 at least doesn't). For 'level editor' I wouldn't do it. – Dalen Jul 30 '15 at 11:59
0

You are looking for eval function

eval is a function that takes arbitrary python code represented as a string and execute it at run time.

Example

>>> x = 1
>>> y = eval('x+1')
>>> print(y)
2

It works in both Python 2.x and 3.x

Check the documentation : https://docs.python.org/2.7/library/functions.html#eval

Hamza Abbad
  • 564
  • 3
  • 15
  • 2
    No it does not! eval() evaluates Python expressions, it doesn't execute arbitrary code. Try: 'eval("print 'abcd'")' and you'll get SyntaxError. :D But you're only half-wrong, as eval() allows execution of code objects and they may contain anything, not just expressions. So: 'eval(compile("print 'abcd'", "blah.py", "exec"))' will work. – Dalen Jul 29 '15 at 16:21
  • Thanks for the informations ! Next time I will test before answering – Hamza Abbad Jul 29 '15 at 17:26
0

So I wanted to do the same thing. I came across this: GeeksforGeeks. With this we could make a text file. Let's say it's called myfile.txt and in the first line we will add print("ok") in the second add A += 1. Now let's move over to the script editor.

# open txt file
f = open("myfile.txt", "r")
# add the data in the file the a var
data = f.readlines()
# remove unwanted \n for new lines and '' left over by the code above
# readlines() returns a list so we need to convert data to str
# in data[] add the line you wish to read from
info = str(data[0]).strip("\n").strip("'")
# run the code
exec(info)
# running the A += 1 in the txt file
# run this
A = 0
info = str(data[1]).strip("\n").strip("'")
while A == 0:
   print(A)
   exec(info)
print(A)
# if you wanted too you can even define a variable with this
alist = ["B = 0", "B += 1", "print(B)"]
runner = [0, 1, 2, 1, 2, 0, 2]
for i in range(len(runner)):
    exec(alist[int(runner[i])])
Dean
  • 11
  • 3