git.net

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

What's the difference between running a script under command box and interpreter?


Cameron Simpson? 2019?11?1???? UTC+8??12?13?45????
> On 31Oct2019 20:44, Jach Fong <jfong at ms4.hinet.net> wrote:
> >The script test.py is something like this:
> >-------test.py
> >from pyeds import fsm
> >...
> >...
> >class Rule_Parse:
> >    def __init__(self):
> >        ...
> >        self.current_char = ''
> >...
> >...
> >def main(input_str):
> >    for c in input_str:
> >        ...
> >        rule.current_char = c
> >        ...
> >
> >if __name__ == '__main__':
> >    input_str = '(NNS(acoustics) & RB(not)) | JJ(muted)'
> >    rule = Rule_Parse()
> >    main(input_str)
> >    ...
> >
> >-----------
> >The test.py can run correctly under command box:
> >D:\Works\Python\pyeds-master\src>py test.py
> >
> >but fails when running under interpreter:
> >D:\Works\Python\pyeds-master\src>py
> >Python 3.4.4 (v3.4.4:737efcadf5a6, Dec 20 2015, 19:28:18) [MSC v.1600 32 bit (Intel)] on win32
> >Type "help", "copyright", "credits" or "license" for more information.
> >>>> from test import *
> >>>> input_str = "(NNS(acoustics) & RB(not)) | JJ(muted)"
> >>>> rule = Rule_Parse()
> >>>> main(input_str)
> >Traceback (most recent call last):
> >  File "<stdin>", line 1, in <module>
> >  File "D:\Works\Python\pyeds-master\src\test.py", line 229, in main
> >    rule.current_char = c
> >NameError: name 'rule' is not defined
> >>>>
> >
> >I did check the globals using dir() and the 'rule' is there, no doubt.
> 
> It matters how you checked this. This isn't apparent.
> 
> >I also tried "py -m pdb test.py" and step through it, no problem too.
> 
> This:
>   py test.py
> and this:
>   py -m pdb test
> 
> both run test.py with __name__ set to "__main__" to indicate that 
> test.py is the main programme.
> 
> When you "import test", the module's __name__ is from the import 
> ("test") i.e. not the main programme.
> 
> The bottom of your module has an if statement whose body only runs when 
> this is the main programme.
> 
> The core issue is that the global "rule" is _only_ defined inside that 
> if statement.
> 
> You might set it unconditionally to None at the start of the file, but 
> that would only change the failure mode.
> 
> You might set it unconditionally to Rule_Parse() at the top of the file 
> but that pointlessly instantiates an instance of Rule_Parse which might 
> never be needed (maybe that is cheap, but many other classes are not).  
> The basic intent of an import is to define various classes and other 
> names, but _not_, generally, to create class instances and do 
> significant work.
> 
> This is really an example illustrating one reason why global variables 
> are considered things to avoid almost all of the time. Had main() 
> required "rule" as a parameter then it would not have been possible to 
> call it without at least providing a rule. The same applies with most 
> other functions: if they all require their external state via parameters 
> then you can't miss things out. (You can, of course, always pass 
> incorrect values, but that is usually easier to debug.)
> 
> Avoid globals; they are usually a source of bugs.
> 
> Cheers,
> Cameron Simpson <cs at cskk.id.au>

Yes, the 'if' body is not executed when I import test.py under interpreter, that's why I manually execute them there.

What puzzles me is that the globals() has a 'rule' object in both cases. Why this one doesn't work?

--Jach