Search code examples
pythonoperating-systemexecsystem

exec() python command stops the whole execution


I am trying to run a script that sequentially changes some parameters in a config file (MET_config_EEv40.cfg) and runs a script ('IS_MET_EEv40_RAW.py') that retrieves these new config parameters:

config_filename = os.getcwd() + '/MET_config_EEv40.cfg'

import sys
parser = configparser.ConfigParser()
parser.read('MET_config_EEv40.cfg')
parser.set('RAW', 'product', 'ERA')
parser.set('RAW', 'gee_product', 'ECMWF/ERA5_LAND/HOURLY')
parser.set('RAW', 'indicator', 'PRCP')
parser.set('RAW', 'resolution', '11110')


with open('MET_config_EEv40.cfg', 'w') as configfile:
    parser.write(configfile)

## execute file
import sys

os.system(exec(open('IS_MET_EEv40_RAW.py').read()))
#exec(open('IS_MET_EEv40_RAW.py').read())

print('I am here')

After this execution, I get the output of my script as expected:

Period of Reference: 2005 - 2019
Area of Interest: /InfoSequia/GIS/ink/shp_basin_wgs84.shp
Raw data is up to date. No new dates available in raw data
Press any key to continue . . .

But it never prints the end line: I am here, so that means that after the execution of the script, the algorithm is terminated. That is not what I want it to do, as I would like to be able to change some other config parameters and run the script again.

That output is showed because of this line of the code:

if (delta.days<=1):
    sys.exit('Raw data is up to date. No new dates available in raw data')

So could be that sys.exit is ending both processes? Any ideas to replace sys.exit() inside the code to avoid this?

Im executing this file from a .bat file that contains the following:

@echo OFF

docker exec container python MET/PRCPmain.py

pause

Solution

  • exec(source, globals=None, locals=None, /) does

    Execute the given source in the context of globals and locals.

    So

    import sys
    exec("sys.exit(0)")
    print("after")
    

    is same as writing

    import sys
    sys.exit(0)
    print("after")
    

    which obviously terminate and does not print after. exec has optional argument globals which you can use to provide your alternative to sys for example

    class MySys:
        def exit(self, *args):
            pass
    exec("sys.exit(0)",{"sys":MySys()})
    print("after")
    

    which does output

    after
    

    as it does use exit from MySys instance. If your codes make use of other things from sys and want it to work normally you would need method mimicking sys function in MySys class