Path: csiph.com!weretis.net!feeder4.news.weretis.net!newsreader4.netcologne.de!news.netcologne.de!newsfeed.kamp.net!newsfeed.kamp.net!fu-berlin.de!uni-berlin.de!not-for-mail From: Chris Angelico Newsgroups: comp.lang.python Subject: Re: Technique for safely reloading dynamically generated module Date: Fri, 22 Jul 2016 00:55:08 +1000 Lines: 54 Message-ID: References: <1469112141.379402.672830825.05659985@webmail.messagingengine.com> Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 X-Trace: news.uni-berlin.de hLFmPgJCe+nrpAFs6W0XyQYt/tdWKxpLrG3Ovv10FnHg== Return-Path: X-Original-To: python-list@python.org Delivered-To: python-list@mail.python.org X-Spam-Status: OK 0.003 X-Spam-Evidence: '*H*': 0.99; '*S*': 0.00; 'cc:addr:python-list': 0.09; '22,': 0.09; 'craft': 0.09; 'subject:module': 0.09; 'python': 0.10; '"this': 0.13; 'appropriate': 0.14; 'file,': 0.15; '2016': 0.16; 'compile,': 0.16; 'enough.': 0.16; 'from:addr:rosuav': 0.16; 'from:name:chris angelico': 0.16; 'function).': 0.16; 'language)': 0.16; 'malcolm': 0.16; 'missing,': 0.16; 'personally,': 0.16; 'received:io': 0.16; 'received:psf.io': 0.16; 'reload': 0.16; 'sys.path': 0.16; 'true:': 0.16; 'wrote:': 0.16; 'string,': 0.18; 'runs': 0.18; 'cc:2**0': 0.20; 'cc:addr:python.org': 0.20; 'exec': 0.22; 'explicit': 0.22; 'function,': 0.22; 'visible': 0.22; 'am,': 0.23; 'code.': 0.23; 'this:': 0.23; 'import': 0.24; 'header:In-Reply- To:1': 0.24; 'sort': 0.25; 'module': 0.25; "doesn't": 0.26; 'fri,': 0.27; 'message-id:@mail.gmail.com': 0.27; 'function': 0.28; 'loop,': 0.29; 'admin': 0.29; 'handled': 0.29; "we're": 0.30; 'code': 0.30; 'skip:g 30': 0.30; "i'd": 0.31; 'probably': 0.31; 'run': 0.33; 'source': 0.33; 'file': 0.34; 'server': 0.34; 'gets': 0.35; 'received:google.com': 0.35; 'something': 0.35; 'step': 0.36; 'but': 0.36; 'there': 0.36; 'created': 0.36; 'subject:: ': 0.37; 'associated': 0.38; 'version': 0.38; 'anything': 0.38; 'whatever': 0.39; 'application': 0.39; 'some': 0.40; 'your': 0.60; 'avoid': 0.61; 'here.': 0.62; 'more': 0.63; 'our': 0.64; 'techniques': 0.65; 'jul': 0.72; 'chrisa': 0.84; 'dsl': 0.84; "everything's": 0.84; 'it"': 0.84; 'of?': 0.84; 'to:none': 0.91; 'organized,': 0.91 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=mime-version:in-reply-to:references:from:date:message-id:subject:cc; bh=bIT14iaXSs3z7LEgSZG5unUrzpniVe/EWK31Bw1gplc=; b=teaHTOsWwkkeTI1QSH9zKMT9htEjiXzgUspeJbAofh9UvmGMQmdBvIqDZseMSYsM8R Wqj8YSHXCJiL+hKjPeGXRwswGIgLxmNneWiuOl60FaZapgBmmUpXRl5RBPk2jfCfjo2l rjEjfKKPgr/Ph09QHQ9wkILzpkxnU+pYhPc2Ru1V0IWnZ0ABl7gkzinipFGVwJltWFpq FXqd4L3QwMdOXFzvfNWGoXzfL7TMH2DSPtasEgIYWKahMA6IXjQIyLUmSMkttuDDgbZi i99uBXhKN1628f0SU/OPA/02X06kW8Fna/VpDn59fI+ba8epUKLUriLDzJYeDuC3cT+e qK3A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:mime-version:in-reply-to:references:from:date :message-id:subject:cc; bh=bIT14iaXSs3z7LEgSZG5unUrzpniVe/EWK31Bw1gplc=; b=eZZIZS2/P/ZGL0RixiiokQ/bolle0AUTLFCiJMSb5oSBXv/3K1OLTTypOmHSgezF3r ybzOs+RcsmKocjVsKtiuzqJ0O4NWBJxsMHXPXdD7DdA+KuKlIAFkJFOuAsJ87YrDM0tA WHAWE7sQ0q6HwBkcOU4123Y+1pHosvVkWNLr41FruduN/zdjqFphfNNCVwm3l7X+WmbQ dzcj3GRVxmoPlo6+eMwPN/b6tMOiEA66OunYL3SfyaZPcCTfmBHpA/VnzsT6M84EpYnP 7uk2LRdBNmb7Y47hoL9agcrLL01+Hy/7WsUOk3Xolg8CFsSL1kkZxF4EcQWDOYSQcbRM 6H+w== X-Gm-Message-State: ALyK8tKoSRowPw8Gg2GmXH3eYOkcMarYl2MgMwofpgaH1emtpfu7FaASNk0HwqaDRTFtfPU/YXCcMs2a2JW2cA== X-Received: by 10.28.172.133 with SMTP id v127mr2750153wme.81.1469112911008; Thu, 21 Jul 2016 07:55:11 -0700 (PDT) In-Reply-To: <1469112141.379402.672830825.05659985@webmail.messagingengine.com> X-BeenThere: python-list@python.org X-Mailman-Version: 2.1.22 Precedence: list List-Id: General discussion list for the Python programming language List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Mailman-Original-Message-ID: X-Mailman-Original-References: <1469112141.379402.672830825.05659985@webmail.messagingengine.com> Xref: csiph.com comp.lang.python:111716 On Fri, Jul 22, 2016 at 12:42 AM, Malcolm Greene wrote: > We're designing a server application that parses a custom DSL (domain > specific language) source file, generates a Python module with the > associated logic, and runs the associated code. Since this is a server > application, we need to reload the module after each regeneration. Is > this process is simple as the following pseudo code or are there other > issues we need to be aware of? Are there better techniques for this > workflow (eval, compile, etc)? > > We're working in Python 3.5.1. > > import importlib > > # custom_code is the module our code will generate - a version of this > # file will always be present > # if custom_code.py is missing, a blank version of this file is created > # before this step > import custom_code > > while True: > # (re)generates custom_code.py visible in sys.path > generate_custom_code( source_file ) > > # reload the module whose source we just generated > importlib.reload( custom_code ) > > # run the main code in generated module > custom_code.go() > I would avoid importlib.reload() if I can. Using compile/eval is probably more effective; you might need to change how the module gets organized, but if you already require a go() function, that's probably enough. Something like this: while True: python_code = generate_custom_code(source_file) ns = {} exec(python_code, ns) ns["go"]() (Presumably your go() function doesn't return until you want to regenerate the code?) Personally, what I'd do is have an initializer function, and have that register the module in whatever way is appropriate (eg some sort of "handle_request" function). Then the main program runs an event loop, everything's handled asynchronously, and you can have either a file system trigger "this file has changed, go and regenerate it" or an explicit action by the admin to regenerate. But definitely I'd craft the source code as a string, not writing anything to disk, and exec it directly; the import machinery is unnecessary here. ChrisA