0

So I am trying to make a python program to write some code to itself the run the code it created before the session ends, like this:

for i in range(10):
    with open('test.py','a') as f:
        f.writelines('    print("Hello World!")\n')

So, the 3rd line creates a 4th line which would print 'Hello World!', next iteration it would print it twice (because then it would have created yet another line saying the same thing) all the way up to 10 iterations. So, in the end, it looks like this:

for i in range(10):
    with open('test.py','a') as f:
        f.writelines('    print("Hello World!")\n')
    print("Hello World!")
    print("Hello World!")
    print("Hello World!")
    ... Up to 10

(However, I mainly want to store outputted data into a variable from this, not prints or anything along those lines).

The problem is that it doesn't update fast enough. When you run the program for the first time you get nothing, then if you close and reopen the code you see all ten 'print('Hello World!')'s. I have no clue how to solve this...

Thanks!

MartinM
  • 209
  • 2
  • 10
  • 1
    You can't modify your script at runtime, afaik. Since the program needs to be compiled first which takes time. Generally it is never a good idea to self modify a script. If you tell us what you want to achieve, there is probably a better way to fix that issue, but you can't modify a running script – J.Paravicini Aug 10 '19 at 11:58
  • What I want to do if have an AI (not important) create some code, then it runs the code and gets the output of it's script, then if the output meets certain conditions (ie: it is a list and, if so does it have a length > 3?) it can pass. This output however cant be a something like a string. Thats why I am not putting it into another python file and getting that output, because I could only get it to be a string when I tried. – MartinM Aug 10 '19 at 12:46
  • You can probably achieve something like this, just not like you showed. As i said, you can't just modify an existing file and expect the program to understand it, as it needs to be compiled first. What you can do is do something called dynamic code creation. [this post](https://stackoverflow.com/questions/11291242/python-dynamically-create-function-at-runtime) talks a bit about it. – J.Paravicini Aug 10 '19 at 13:14
  • But in all honesty, I am not a fan of dynamically creating code, it is meant for automatic generating code, but if you still want it, the post i linked should help you go forward – J.Paravicini Aug 10 '19 at 13:15

1 Answers1

0

The way you want your program to be dynamically written is possible. (But be mindful, that there are sure better alternatives than this answer provides)

First, you need to have an empty 'program.py' (or any other name) in your import path. Then it is possible to modify program.py on the fly. The trick is that you can reload your program as a module in python, which will execute it.


import os
from importlib import reload
import program
from io import StringIO
from unittest import mock


def write_program(list_that_contains_strings_that_are_lines, force_new=False):
    mode = 'w' if not os.path.exists('program.py') or force_new else 'a+'
    with open('program.py', mode) as f:
        f.writelines(list_that_contains_strings_that_are_lines)


lines = ['print("Hello!")\n' for _ in range(5)]

out_stream = StringIO()
with mock.patch('sys.stdout', out_stream):
    write_program(lines)
    reload(program)

out_stream.getvalue()

and program.py will have 5 print statements in the end.

Also, take a look into How can I make one python file run another? for detailed explanation.


Edit: You can redirect stdout stream to some buffer.

Drey
  • 3,314
  • 2
  • 21
  • 26