Ipython: IPythonShellEmbed рд╕реНрдерд╛рдиреАрдп рдЪрд░реЛрдВ рдХреЛ рдкрд╣рдЪрд╛рдирдиреЗ рдореЗрдВ рд╡рд┐рдлрд▓ рд░рд╣рддрд╛ рд╣реИ

рдХреЛ рдирд┐рд░реНрдорд┐рдд 19 рдЬреБрд▓ре░ 2010  ┬╖  18рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ  ┬╖  рд╕реНрд░реЛрдд: ipython/ipython

рдореБрджреНрджрд╛

рдПрдВрдмреЗрдбреЗрдб IPython рд╢реЗрд▓ рд╕реНрдерд╛рдиреАрдп рдЪрд░ рдХрд╛ рдЯреНрд░реИрдХ рдЦреЛ рд╕рдХрддреЗ рд╣реИрдВред

рдкрд░реАрдХреНрд╖рдг рдХрд╛ рдорд╛рдорд▓рд╛

рдиреНрдпреВрдирддрдо рдкрд░реАрдХреНрд╖рдг рдорд╛рдорд▓рд╛:

class Foo(object):
    """ Container-like object """
    def __setattr__(self, obj, val):
        self.__dict__[obj] = val

    def __getattr__(self, obj, val):
        return self.__dict__[obj]

f = Foo()
f.indices = set([1,2,3,4,5])
f.values = {}
for x in f.indices:
    f.values[x] = x

def bar(foo):
    import IPython
    IPython.Shell.IPShellEmbed()()
    return sum(foo.values[x] for x in foo.indices)

print bar(f)

рддреНрд░реБрдЯрд┐ рджреЗрдЦрдиреЗ рдХреЗ рд▓рд┐рдП, рдкрд╣рд▓реЗ рдХреЛрдб рдХреЛ Python (рдпрд╛ IPython) рдореЗрдВ рдЪрд▓рд╛рдПрдВ рдФрд░ рд╕реНрдкреЙрдиреНрдб рд╢реЗрд▓ рд╕реЗ рдмрд╛рд╣рд░ рдирд┐рдХрд▓реЗрдВ; рдЕрдВрддрд┐рдо рдкреНрд░рд┐рдВрдЯ рд╕реНрдЯреЗрдЯрдореЗрдВрдЯ '15' рдХреЛ рд╕рд╣реА рдврдВрдЧ рд╕реЗ рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд░рддрд╛ рд╣реИред рдХреЛрдб рдХреЛ рдлрд┐рд░ рд╕реЗ рдЪрд▓рд╛рдПрдБ, рд▓реЗрдХрд┐рди рдЗрд╕ рдмрд╛рд░ рд╕реНрдкреЙрдиреНрдб рд╢реЗрд▓ рдореЗрдВ sum(foo.values[x] for x in foo.indices) рдЯрд╛рдЗрдк рдХрд░реЗрдВ, рдФрд░ рд╣рдореЗрдВ рддреНрд░реБрдЯрд┐ рдкреНрд░рд╛рдкреНрдд рд╣реЛрддреА рд╣реИ

"рдирд╛рдо рддреНрд░реБрдЯрд┐: рд╡реИрд╢реНрд╡рд┐рдХ рдирд╛рдо 'рдлреВ' рдкрд░рд┐рднрд╛рд╖рд┐рдд рдирд╣реАрдВ рд╣реИ"ред

рд╕рдмрд╕реЗ рдЙрдкрдпреЛрдЧреА рдЯрд┐рдкреНрдкрдгреА

рдореИрдВрдиреЗ рдЗрд╕ рдореБрджреНрджреЗ рдкрд░ рдереЛрдбрд╝рд╛ рдзреНрдпрд╛рди рджрд┐рдпрд╛, рдФрд░ рдпрд╣ рдирд┐рд╢реНрдЪрд┐рдд рд░реВрдк рд╕реЗ рдареАрдХ рдХрд░рдиреЗ рдпреЛрдЧреНрдп рд╣реИ (рд╣рд╛рд▓рд╛рдВрдХрд┐ рдкрд╛рдпрдерди 2 рдФрд░ 3 рджреЛрдиреЛрдВ рдХреЗ рд▓рд┐рдП рд╕реБрдзрд╛рд░ рдмрдирд╛рдП рд░рдЦрдирд╛ рдЧрдбрд╝рдмрдбрд╝ рд╣реЛ рд╕рдХрддрд╛ рд╣реИ)ред

IPython рдореЗрдВ рдЙрдЪрд┐рдд рд░реВрдк рд╕реЗ рд╢рд╛рдорд┐рд▓ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП ChainMap рд╕рдорд╛рдзрд╛рди рд╕рдмрд╕реЗ рдЖрд╕рд╛рди рд╣реЛрдЧрд╛ред рд╣рд╛рд▓рд╛рдВрдХрд┐, рдПрдХ рдЫреЛрдЯреА рд╕реА рдкрдХрдбрд╝ рд╣реИ рдХрд┐ eval/exec рдХреЗ рд▓рд┐рдП рдЧреНрд▓реЛрдмрд▓реНрд╕ рдХреЛ dict ред рдПрдХ class MyChainMap(ChainMap, dict): pass рдмрдирд╛рдирд╛ рдЗрд╕ рдХреЗ рдЖрд╕рдкрд╛рд╕ рдХрд╛рдо рдХрд░ рд╕рдХрддрд╛ рд╣реИред

рдореИрдВрдиреЗ рдХреНрд▓реЛрдЬрд░ рд╕реЗрд▓ рдХреЛ рд╕рд┐рдореНрдпреБрд▓реЗрдЯ рдХрд░рдиреЗ рдФрд░ рдкрд╛рдЗрдерди рдХрдВрдкрд╛рдЗрд▓рд░ рдХреЛ рдЙрдирдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╕рд╣реА рдмрд╛рдЗрдЯрдХреЛрдб рдЙрддреНрд╕рд░реНрдЬрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдордЬрдмреВрд░ рдХрд░рдиреЗ рдХреА рдПрдХ рдЕрд▓рдЧ рд░рдгрдиреАрддрд┐ рдХреЗ рдЖрдзрд╛рд░ рдкрд░ рдПрдХ рдкрд╛рдпрдерди 3.5+ рдлрд┐рдХреНрд╕ рднреА рд▓рд┐рдЦрд╛ рдерд╛ред рдкреНрд░рд╛рд╕рдВрдЧрд┐рдХ рдлрд╝рд╛рдЗрд▓ рдпрд╣рд╛рдБ рд╣реИ , рдореЗрд░реЗ xdbg рдбреЗрдореЛ рдХрд╛ рд╣рд┐рд╕реНрд╕рд╛ рд╣реИред рдпрд╣ get_ipython().run_ast_nodes рдХреЛ рдмрджрд▓рдХрд░ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИред

рдЬрд╣рд╛рдВ рддрдХ тАЛтАЛтАЛтАЛрдореИрдВ рдХрд╣ рд╕рдХрддрд╛ рд╣реВрдВ, рджреЛ рджреГрд╖реНрдЯрд┐рдХреЛрдг рдХреЗрд╡рд▓ рдмрдВрдж рд╣реЛрдиреЗ рд╕реЗ рдирд┐рдкрдЯрдиреЗ рдореЗрдВ рднрд┐рдиреНрди рд╣реЛрддреЗ рд╣реИрдВред рдЬрдм xdbg рдХреЛ рдЙрд╕ рджрд╛рдпрд░реЗ рдореЗрдВ рдПрдореНрдмреЗрдб рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рдЬреЛ рдХреБрдЫ рдЪрд░реЛрдВ рдкрд░ рдмрдВрдж рд╣реЛ рдЧрдпрд╛ рд╣реИ, рддреЛ рдпрд╣ рд╕рдВрджрд░реНрдн рджреНрд╡рд╛рд░рд╛ рдЙрди рдЪрд░реЛрдВ рддрдХ рд╕рд╣реА рдврдВрдЧ рд╕реЗ рдкрд╣реБрдВрдЪ рд╕рдХрддрд╛ рд╣реИ рдФрд░ рдЙрдиреНрд╣реЗрдВ рдмрджрд▓ рд╕рдХрддрд╛ рд╣реИред рдЗрд╕рдХреЗ рдЕрддрд┐рд░рд┐рдХреНрдд, рдпрджрд┐ рдЗрдВрдЯрд░реЗрдХреНрдЯрд┐рд╡ рджреБрднрд╛рд╖рд┐рдпрд╛ рдореЗрдВ рдХреЛрдИ рдлрд╝рдВрдХреНрд╢рди рдмрдирд╛рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рддреЛ рд╡реЗ рдХрд┐рд╕реА рднреА рд╕реНрдерд╛рдиреАрдп рдЪрд░ рдХреЛ рдмрдВрдж рдХрд░ рджреЗрдВрдЧреЗ, рдЬрдмрдХрд┐ рдмрд╛рдХреА рд╕реНрдерд╛рдиреАрдп рджрд╛рдпрд░реЗ рдХреЛ рдХрдЪрд░рд╛ рдПрдХрддреНрд░ рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИред

рд╕рднреА 18 рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ

рд╣рдореНрдо, рдЖрдкрдиреЗ 'рдлреВ' рдХреЛ рдХрд╣рд╛рдВ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд┐рдпрд╛?

рдпрджрд┐ рдЖрдк рдлрд╝рдВрдХреНрд╢рди рдмрд╛рд░ рдХреЗ рдмрд╛рд╣рд░ рдХреЙрд▓ рдлреВ рдЪрд▓рд╛рддреЗ рд╣реИрдВ, рддреЛ рдлреВ рдореМрдЬреВрдж рдирд╣реАрдВ рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдП (рдФрд░ рдирд┐рд╢реНрдЪрд┐рдд рд░реВрдк рд╕реЗ рдпрд╣ рдирд╣реАрдВ рд╣реИ)ред

рдЬрдм рдЖрдк рдЗрд╕рдХреЗ рдмрдЬрд╛рдп "рдпреЛрдЧ (f.values тАЛтАЛ[x] x рдХреЗ рд▓рд┐рдП f.indices рдореЗрдВ) рдЪрд▓рд╛рддреЗ рд╣реИрдВ, рддреЛ рдЖрдкрдХреЛ рдлрд┐рд░ рд╕реЗ 15 рдорд┐рд▓рддреЗ рд╣реИрдВ ...

рдПрдХрджрдо рд╕рд╣реАред рд╣рд╛рд▓рд╛рдБрдХрд┐, рдореИрдВ foo _inside_ рд╕реНрдкреЙрдиреНрдбреЗрдб IPython рд╢реЗрд▓ рдХреЗ рдЙрдкрдпреЛрдЧ рдХреА рдмрд╛рдд рдХрд░ рд░рд╣рд╛ рд╣реВрдБ, рдЬреЛ рдмрджрд▓реЗ рдореЗрдВ рдлрд╝рдВрдХреНрд╢рди рдкрд░рд┐рднрд╛рд╖рд╛ рдХреЗ рдЕрдВрджрд░ рдЙрддреНрдкрдиреНрди рд╣реЛрддрд╛ рд╣реИ рдЬрд╣рд╛рдБ foo рдПрдХ рд╕реНрдерд╛рдиреАрдп рдЪрд░ рд╣реИред

рдХреНрдпрд╛ рдпрд╣ #62 рдЬреИрд╕рд╛ рд╣реА рдореБрджреНрджрд╛ рд╣реЛрдиреЗ рдХреА рд╕рдВрднрд╛рд╡рдирд╛ рд╣реИ?

рдирд╣реАрдВ, @takluyver : рдпрд╣ рдПрдХ рдЕрд▓рдЧ рдореБрджреНрджрд╛ рд╣реИ рдФрд░ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рд╣рдорд╛рд░реЗ рдПрдореНрдмреЗрдбрд┐рдВрдЧ рдХреЛрдб рдореЗрдВ рдПрдХ рд╡рд╛рд╕реНрддрд╡рд┐рдХ рдмрдЧ рд╣реИред рдореИрдВ рдЙрдореНрдореАрдж рдХрд░ рд░рд╣рд╛ рдерд╛ рдХрд┐ рдиреЗрдорд╕реНрдкреЗрд╕ рдХреЗ рд╕рд╛рде рдЖрдкрдХреЗ рд╣рд╛рд▓рд┐рдпрд╛ рдХрд╛рдо рдиреЗ рдЗрд╕реЗ рдареАрдХ рдХрд░ рджрд┐рдпрд╛ рд╣реЛрдЧрд╛, рд▓реЗрдХрд┐рди рдРрд╕рд╛ рдирд╣реАрдВ рд╣реБрдЖред рд╕рдВрджрд░реНрдн рдХреЗ рд▓рд┐рдП, рд╡рд░реНрддрдорд╛рди рдПрдореНрдмреЗрдбрд┐рдВрдЧ рдПрдкреАрдЖрдИ рдХреЗ рд╕рд╛рде рдЪрд▓рд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдЙрджрд╛рд╣рд░рдг рдХреЛрдб рдпрд╣рд╛рдВ рджрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ:

class Foo(object):
    """ Container-like object """
    def __setattr__(self, obj, val):
        self.__dict__[obj] = val

    def __getattr__(self, obj, val):
        return self.__dict__[obj]

f = Foo()
f.indices = set([1,2,3,4,5])
f.values = {}
for x in f.indices:
    f.values[x] = x

def bar(foo):
    import IPython
    IPython.embed()
    return sum(foo.values[x] for x in foo.indices)

print bar(f)

рдлрд┐рд░, рдЙрддреНрдкрдиреНрди, рдПрдореНрдмреЗрдбреЗрдб IPython рдореЗрдВ, рдпрд╣ рд╡рд┐рдлрд▓ рд░рд╣рддрд╛ рд╣реИ:

In [1]: sum(foo.values[x] for x in foo.indices)
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
/home/fperez/tmp/junk/ipython/foo.py in <module>()
----> 1 sum(foo.values[x] for x in foo.indices)

/home/fperez/tmp/junk/ipython/foo.py in <genexpr>((x,))
----> 1 sum(foo.values[x] for x in foo.indices)

NameError: global name 'foo' is not defined

рдФрд░ рдпрд╣ рдХрд╛рдо рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИ, рднрд▓реЗ рд╣реА рд╣рдо рдПрдореНрдмреЗрдб рдХреЙрд▓ user_ns=locals() рд╕реНрдкрд╖реНрдЯ рд░реВрдк рд╕реЗ рдкрд╛рд╕ рдХрд░рддреЗ рд╣реИрдВ, рд▓реЗрдХрд┐рди рдЙрд╕ рд╕реНрдерд┐рддрд┐ рдореЗрдВ рд╣рдореЗрдВ рдмрд╛рд╣рд░ рдирд┐рдХрд▓рдиреЗ рдкрд░ рдПрдХ рджреБрд░реНрдШрдЯрдирд╛ рдорд┐рд▓рддреА рд╣реИ:

Error in atexit._run_exitfuncs:
Traceback (most recent call last):
  File "/usr/lib/python2.7/atexit.py", line 24, in _run_exitfuncs
    func(*targs, **kargs)
  File "/home/fperez/usr/lib/python2.7/site-packages/IPython/core/interactiveshell.py", line 2702, in atexit_operations
    self.reset(new_session=False)
  File "/home/fperez/usr/lib/python2.7/site-packages/IPython/core/interactiveshell.py", line 1100, in reset
    self.displayhook.flush()
  File "/home/fperez/usr/lib/python2.7/site-packages/IPython/core/displayhook.py", line 319, in flush
    self.shell.user_ns['_oh'].clear()
KeyError: '_oh'

рдРрд╕рд╛ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рд╣рдорд╛рд░реА рдПрдореНрдмреЗрдбрд┐рдВрдЧ рдорд╢реАрдирд░реА рдмрд╣реБрдд рдЦрд░рд╛рдм рд╕реНрдерд┐рддрд┐ рдореЗрдВ рд╣реИ...

рдпрд╣ рджреЗрдЦрдиреЗ рдХреЗ рд▓рд┐рдП рдЦреБрдж рдХреЛ рд╕реМрдВрдкрд╛ред

рдЙрддреНрдХреГрд╖реНрдЯ рдзрдиреНрдпрд╡рд╛рджред

рджреБрд░реНрднрд╛рдЧреНрдп рд╕реЗ, рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдпрд╣ рдкрд╛рдпрдерди рдХреА рд╣реА рдПрдХ рд╕реАрдорд╛ рд╣реИред рдРрд╕рд╛ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдЧрддрд┐рд╢реАрд▓ рд░реВрдк рд╕реЗ рд╕рдВрдХрд▓рд┐рдд рдХреЛрдб рдПрдХ рдХреНрд▓реЛрдЬрд░ рдХреЛ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдирд╣реАрдВ рдХрд░ рд╕рдХрддрд╛ рд╣реИ, рдЬреЛ рдЕрдирд┐рд╡рд╛рд░реНрдп рд░реВрдк рд╕реЗ рд╣рдо рдпрд╣рд╛рдВ рдЬрдирд░реЗрдЯрд░ рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐ рдХреЗ рд╕рд╛рде рдХрд░ рд░рд╣реЗ рд╣реИрдВред рдпрд╣рд╛рдБ рдПрдХ рдиреНрдпреВрдирддрдо рдкрд░реАрдХреНрд╖рдг рдорд╛рдорд▓рд╛ рд╣реИ:

def f():
   x = 1
   exec "def g(): print x\ng()"

f()

рдЬреЛ рджреЗрддрд╛ рд╣реИ:

Traceback (most recent call last):
  File "scopetest.py", line 5, in <module>
    f()
  File "scopetest.py", line 3, in f
    exec "def g(): print x\ng()"
  File "<string>", line 2, in <module>
  File "<string>", line 1, in g
NameError: global name 'x' is not defined

рдзреНрдпрд╛рди рджреЗрдВ рдХрд┐ рдЖрдк рдЕрднреА рднреА IPython рдореЗрдВ рд╕реНрдерд╛рдиреАрдп рдЪрд░ рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВ - рджрд┐рдП рдЧрдП рдЙрджрд╛рд╣рд░рдг рдореЗрдВ, рд╕рд╛рджрд╛ print foo рдХрд╛рдо рдХрд░рддрд╛ рд╣реИред рд▓реЗрдХрд┐рди рдЖрдк рдЙрди рдкрд░ рдПрдХ рдирдпрд╛ рджрд╛рдпрд░рд╛ рдмрдВрдж рдирд╣реАрдВ рдХрд░ рд╕рдХрддреЗред

рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдкрд╛рдЗрдерди 3.3 рд╕реЗ collections.ChainMap рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдпрд╣ рдХрд╛рдо рдХрд░рдирд╛ рд╕рдВрднрд╡ рд╣реЛ рд╕рдХрддрд╛ рд╣реИ рддрд╛рдХрд┐ рдЖрдИрдкреАрдерди рд╕реНрдерд╛рдиреАрдп рдФрд░ рд╡реИрд╢реНрд╡рд┐рдХ рджреЛрдиреЛрдВ рдЪрд░ рджреЗрдЦ рд╕рдХреЗ рдЬрд╣рд╛рдВ рдЗрд╕реЗ рдЧреНрд▓реЛрдмрд▓реНрд╕ рдХреЗ рд░реВрдк рдореЗрдВ рдПрдореНрдмреЗрдб рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реЛред рд╣рд╛рд▓рд╛рдВрдХрд┐, рдкрд┐рдЫрд▓реЗ рджреЛ рд╡рд░реНрд╖реЛрдВ рдореЗрдВ рдЗрд╕ рдмрд╛рд░реЗ рдореЗрдВ рд╢реЛрд░ рдХреА рдХрдореА рд╕реЗ, рдореБрдЭреЗ рдирд╣реАрдВ рд▓рдЧрддрд╛ рдХрд┐ рдпрд╣ рдЙрдЪреНрдЪ рдкреНрд░рд╛рдердорд┐рдХрддрд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП рдореИрдВ рддрджрдиреБрд╕рд╛рд░ рд░реАрдЯреИрдЧрд┐рдВрдЧ рдХрд░ рд░рд╣рд╛ рд╣реВрдВ, рдФрд░ рдЙрдореНрдореАрдж рд╣реИ рдХрд┐ 1.0 рдХреЗ рдмрд╛рдж рдХреБрдЫ рд╕рдордп рдХреЗ рд▓рд┐рдП рдЗрд╕реЗ рдкреНрд░рд╛рдкреНрдд рдХрд░ рд░рд╣рд╛ рд╣реВрдВред

рдХреНрдпрд╛ рдЕрдк-рд╡реЛрдЯ рдХрд░рдирд╛ рд╕реНрд╡реАрдХрд╛рд░реНрдп рд╣реИ, :+1: ? рдпрд╣ рдореБрдЭреЗ рднреА рдкреНрд░рднрд╛рд╡рд┐рдд рдХрд░рддрд╛ рд╣реИред рдЕрдиреБрд░реЛрдз рдХрд┐рдП рдЬрд╛рдиреЗ рдкрд░ рдореИрдВ рдЕрдкрдирд╛ рдЙрдкрдпреЛрдЧ-рдорд╛рдорд▓рд╛ рдЬреЛрдбрд╝ рд╕рдХрддрд╛ рд╣реВрдВред

рдореИрдВ 100% рдареАрдХ рд╣реЛрдЧрд╛ рдЕрдЧрд░ рдЗрд╕рдХреЗ рд▓рд┐рдП рдлрд┐рдХреНрд╕ рдХреЗрд╡рд▓ рдкрд╛рдпрдерди 3 рдкрд░ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИред

рдореБрдЭреЗ рдкрд╛рдпрдерди 3 рдХреЗ рддрд╣рдд рднреА рдпрд╣реА рд╕рдорд╕реНрдпрд╛ рд╣реЛ рд░рд╣реА рд╣реИред рдкреБрдирдГ рдЦреЛрд▓рдиреЗ рдХреЗ рд▓рд┐рдП рдзрдиреНрдпрд╡рд╛рджред

рдпрд╣рд╛рдВ рд╡рд╣реА рд╕рдорд╕реНрдпрд╛ рд╣реИ: +1: рдкрд╛рдпрдерди 2 рдФрд░ 3 рджреЛрдиреЛрдВ рдореЗрдВред

рдореЗрд░реЗ рдкрд╛рд╕ рдпрд╣ рд╕рдорд╕реНрдпрд╛ рдкрд╛рдпрдерди 2 рдФрд░ 3 рджреЛрдиреЛрдВ рдореЗрдВ рд╣реИред рдпрд╣ рдореБрдЭреЗ рджреИрдирд┐рдХ рдЖрдзрд╛рд░ рдкрд░ рдкреНрд░рднрд╛рд╡рд┐рдд рдХрд░рддрд╛ рд╣реИред

рдореИрдВрдиреЗ рдЗрд╕ рдореБрджреНрджреЗ рдкрд░ рдереЛрдбрд╝рд╛ рдзреНрдпрд╛рди рджрд┐рдпрд╛, рдФрд░ рдпрд╣ рдирд┐рд╢реНрдЪрд┐рдд рд░реВрдк рд╕реЗ рдареАрдХ рдХрд░рдиреЗ рдпреЛрдЧреНрдп рд╣реИ (рд╣рд╛рд▓рд╛рдВрдХрд┐ рдкрд╛рдпрдерди 2 рдФрд░ 3 рджреЛрдиреЛрдВ рдХреЗ рд▓рд┐рдП рд╕реБрдзрд╛рд░ рдмрдирд╛рдП рд░рдЦрдирд╛ рдЧрдбрд╝рдмрдбрд╝ рд╣реЛ рд╕рдХрддрд╛ рд╣реИ)ред

IPython рдореЗрдВ рдЙрдЪрд┐рдд рд░реВрдк рд╕реЗ рд╢рд╛рдорд┐рд▓ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП ChainMap рд╕рдорд╛рдзрд╛рди рд╕рдмрд╕реЗ рдЖрд╕рд╛рди рд╣реЛрдЧрд╛ред рд╣рд╛рд▓рд╛рдВрдХрд┐, рдПрдХ рдЫреЛрдЯреА рд╕реА рдкрдХрдбрд╝ рд╣реИ рдХрд┐ eval/exec рдХреЗ рд▓рд┐рдП рдЧреНрд▓реЛрдмрд▓реНрд╕ рдХреЛ dict ред рдПрдХ class MyChainMap(ChainMap, dict): pass рдмрдирд╛рдирд╛ рдЗрд╕ рдХреЗ рдЖрд╕рдкрд╛рд╕ рдХрд╛рдо рдХрд░ рд╕рдХрддрд╛ рд╣реИред

рдореИрдВрдиреЗ рдХреНрд▓реЛрдЬрд░ рд╕реЗрд▓ рдХреЛ рд╕рд┐рдореНрдпреБрд▓реЗрдЯ рдХрд░рдиреЗ рдФрд░ рдкрд╛рдЗрдерди рдХрдВрдкрд╛рдЗрд▓рд░ рдХреЛ рдЙрдирдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╕рд╣реА рдмрд╛рдЗрдЯрдХреЛрдб рдЙрддреНрд╕рд░реНрдЬрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдордЬрдмреВрд░ рдХрд░рдиреЗ рдХреА рдПрдХ рдЕрд▓рдЧ рд░рдгрдиреАрддрд┐ рдХреЗ рдЖрдзрд╛рд░ рдкрд░ рдПрдХ рдкрд╛рдпрдерди 3.5+ рдлрд┐рдХреНрд╕ рднреА рд▓рд┐рдЦрд╛ рдерд╛ред рдкреНрд░рд╛рд╕рдВрдЧрд┐рдХ рдлрд╝рд╛рдЗрд▓ рдпрд╣рд╛рдБ рд╣реИ , рдореЗрд░реЗ xdbg рдбреЗрдореЛ рдХрд╛ рд╣рд┐рд╕реНрд╕рд╛ рд╣реИред рдпрд╣ get_ipython().run_ast_nodes рдХреЛ рдмрджрд▓рдХрд░ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИред

рдЬрд╣рд╛рдВ рддрдХ тАЛтАЛтАЛтАЛрдореИрдВ рдХрд╣ рд╕рдХрддрд╛ рд╣реВрдВ, рджреЛ рджреГрд╖реНрдЯрд┐рдХреЛрдг рдХреЗрд╡рд▓ рдмрдВрдж рд╣реЛрдиреЗ рд╕реЗ рдирд┐рдкрдЯрдиреЗ рдореЗрдВ рднрд┐рдиреНрди рд╣реЛрддреЗ рд╣реИрдВред рдЬрдм xdbg рдХреЛ рдЙрд╕ рджрд╛рдпрд░реЗ рдореЗрдВ рдПрдореНрдмреЗрдб рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рдЬреЛ рдХреБрдЫ рдЪрд░реЛрдВ рдкрд░ рдмрдВрдж рд╣реЛ рдЧрдпрд╛ рд╣реИ, рддреЛ рдпрд╣ рд╕рдВрджрд░реНрдн рджреНрд╡рд╛рд░рд╛ рдЙрди рдЪрд░реЛрдВ рддрдХ рд╕рд╣реА рдврдВрдЧ рд╕реЗ рдкрд╣реБрдВрдЪ рд╕рдХрддрд╛ рд╣реИ рдФрд░ рдЙрдиреНрд╣реЗрдВ рдмрджрд▓ рд╕рдХрддрд╛ рд╣реИред рдЗрд╕рдХреЗ рдЕрддрд┐рд░рд┐рдХреНрдд, рдпрджрд┐ рдЗрдВрдЯрд░реЗрдХреНрдЯрд┐рд╡ рджреБрднрд╛рд╖рд┐рдпрд╛ рдореЗрдВ рдХреЛрдИ рдлрд╝рдВрдХреНрд╢рди рдмрдирд╛рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рддреЛ рд╡реЗ рдХрд┐рд╕реА рднреА рд╕реНрдерд╛рдиреАрдп рдЪрд░ рдХреЛ рдмрдВрдж рдХрд░ рджреЗрдВрдЧреЗ, рдЬрдмрдХрд┐ рдмрд╛рдХреА рд╕реНрдерд╛рдиреАрдп рджрд╛рдпрд░реЗ рдХреЛ рдХрдЪрд░рд╛ рдПрдХрддреНрд░ рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИред

IPython 6.0 рдФрд░ рдмрд╛рдж рдХреЗ рд╕рдВрд╕реНрдХрд░рдг рдХреЗрд╡рд▓ Python 3 рдореЗрдВ рдХрд╛рдо рдХрд░рддреЗ рд╣реИрдВ, рдЗрд╕рд▓рд┐рдП рдпрджрд┐ @nikitakit рдпрд╛ рдХреЛрдИ рдЕрдиреНрдп рд╡реНрдпрдХреНрддрд┐ рдПрдХ рдкрд░реАрдХреНрд╖рдг рдорд╛рдорд▓реЗ рдХреЗ рд╕рд╛рде рдПрдХ рдкреБрд▓ рдЕрдиреБрд░реЛрдз рдЦреЛрд▓рдирд╛ рдЪрд╛рд╣рддрд╛ рд╣реИ рдФрд░ рдЗрд╕рдХреЗ рд▓рд┐рдП рдПрдХ рдлрд┐рдХреНрд╕ рд╣реИ, рддреЛ рдЗрд╕рдХрд╛ рд╕реНрд╡рд╛рдЧрдд рд╣реЛрдЧрд╛ред

рдпрд╣рд╛рдВ рдореЗрд░реА рдЖрдЦрд┐рд░реА рдЯрд┐рдкреНрдкрдгреА рдХреЛ рдПрдХ рд╕рд╛рд▓ рд╣реЛ рдЧрдпрд╛ рд╣реИ, рдФрд░ рдЗрд╕ рджреМрд░рд╛рди рдЗрд╕ рдореБрджреНрджреЗ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдореЗрд░реА рд╕рдордЭ рдереЛрдбрд╝реА рдмрджрд▓ рдЧрдИ рд╣реИред

рд╕реНрдерд╛рдиреАрдп рджрд╛рдпрд░реЗ рдХрд╛ рдЕрдВрддрдГрдХреНрд░рд┐рдпрд╛рддреНрдордХ рдирд┐рд░реАрдХреНрд╖рдг рдХрд░рдирд╛ рдореЗрд░реЗ рд▓рд┐рдП рдПрдХ рдорд╣рддреНрд╡рдкреВрд░реНрдг рд╡рд┐рд╢реЗрд╖рддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рд╕реНрдерд╛рдиреАрдп рдЪрд░ рдФрд░ рдПрдореНрдмреЗрдбрд┐рдВрдЧ рдорд╢реАрдирд░реА рдХреЗ рд╕рдВрдмрдВрдз рдореЗрдВ рдХрдИ рдЕрдВрддрд░-рд╕рдВрдмрдВрдзрд┐рдд рдореБрджреНрджреЗ рд╣реИрдВред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдПрдХ рдПрдореНрдмреЗрдбреЗрдб рд╢реЗрд▓ рдХреЗ рдЕрдВрджрд░ рд╕реНрдерд╛рдиреАрдп рдЪрд░ рдХреЛ рд╕рдВрд╢реЛрдзрд┐рдд рдХрд░рдирд╛ рдХрд╛рдо рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИ:

>>> import IPython
>>> def test():
...     x = 5
...     IPython.embed()
...     print('x is', x)
...
>>> test()
Python 3.5.1 |Continuum Analytics, Inc.| (default, Dec  7 2015, 11:24:55)
Type 'copyright', 'credits' or 'license' for more information
IPython 6.1.0 -- An enhanced Interactive Python. Type '?' for help.

In [1]: x
Out[1]: 5

In [2]: x = 6

In [3]:
Do you really want to exit ([y]/n)? y

x is 5

рдПрдХ ChainMap -рдЖрдзрд╛рд░рд┐рдд рджреГрд╖реНрдЯрд┐рдХреЛрдг рдЗрд╕ рд╕реНрдерд┐рддрд┐ рдореЗрдВ рдорджрдж рдирд╣реАрдВ рдХрд░реЗрдЧрд╛ред

рдПрдХ рдФрд░ рд╕рд╡рд╛рд▓ рдпрд╣ рд╣реИ рдХрд┐ рдХреНрдпрд╛ рд╣реЛрддрд╛ рд╣реИ рдЬрдм рдПрдХ рдПрдореНрдмреЗрдбреЗрдб рд╢реЗрд▓ рдХреЗ рдЕрдВрджрд░ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХреНрд▓реЛрдЬрд░ рд╡реИрд╢реНрд╡рд┐рдХ рджрд╛рдпрд░реЗ рдореЗрдВ рд▓реАрдХ рд╣реЛ рдЬрд╛рддреЗ рд╣реИрдВред рдКрдкрд░ рдХреЗ рд╕рдорд╛рди рдХреЛрдб рдЪрд▓рд╛рдиреЗ рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░реЗрдВ, рд▓реЗрдХрд┐рди рдПрдореНрдмреЗрдбреЗрдб IPython рд╢реЗрд▓ рдореЗрдВ IPython.get_my_x = lambda: x рдХреА рддрд░реНрдЬ рдкрд░ рдХреБрдЫ рдЗрдирдкреБрдЯ рдХрд░реЗрдВред рдПрдХ ChainMap -рдЖрдзрд╛рд░рд┐рдд рд╕рдорд╛рдзрд╛рди рдЗрд╕ рд╕реНрдерд┐рддрд┐ рдореЗрдВ NameError рдХрд╛ рдХрд╛рд░рдг рдмрдирдиреЗ рд╕реЗ рдмрдЪ рдЬрд╛рдПрдЧрд╛, рд╕рдВрднрд╛рд╡рд┐рдд рд░реВрдк рд╕реЗ x рдХреА рдПрдХ рд╕рд╛рде рджреЛ рдкреНрд░рддрд┐рдпреЛрдВ рдХреЛ рдкреЗрд╢ рдХрд░рдиреЗ рдХреА рдХреАрдордд рдкрд░ рдЬреЛ рдПрдХ рджреВрд╕рд░реЗ рд╕реЗ рд╕реНрд╡рддрдВрддреНрд░ рд░реВрдк рд╕реЗ рдореМрдЬреВрдж рд╣реИрдВ (рдПрдХ рд╣реЛрдиреЗ рдХреЗ рдирд╛рддреЗ) ChainMap , рдФрд░ рджреВрд╕рд░рд╛ рд╕реНрдерд╛рдиреАрдп рдЪрд░/рдХреНрд▓реЛрдЬрд░ рд╕реЗрд▓ рдЬрд┐рд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рдкрд╛рдпрдерди рджреБрднрд╛рд╖рд┐рдпрд╛ рджреНрд╡рд╛рд░рд╛ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ)ред

рд╕реНрдерд┐рддрд┐ рдХреА рдЬрдЯрд┐рд▓рддрд╛ рдХреЛ рджреЗрдЦрддреЗ рд╣реБрдП, рдореИрдВрдиреЗ рдЕрдкрдиреЗ рдкреНрд░рдпрд╛рд╕реЛрдВ рдХреЛ рд╕рдорд╕реНрдпрд╛ рдХреЗ рдЕрдзрд┐рдХ рд╡реНрдпрд╛рдкрдХ рджреГрд╖реНрдЯрд┐рдХреЛрдг рдкрд░ рдХреЗрдВрджреНрд░рд┐рдд рдХрд░рдиреЗ рдХрд╛ рдирд┐рд░реНрдгрдп рд▓рд┐рдпрд╛ рд╣реИ (рдЬреЛ рдХрд┐ рдЖрдИрдкреАрдереЙрди рдХреЗ рдЕрдкрдиреЗ рдЙрдкрдпреЛрдЧ рдХреЗ рд╕рд╛рде рдмреЗрд╣рддрд░ рд░реВрдк рд╕реЗ рд╕рдВрд░реЗрдЦрд┐рдд рд╣реИ)ред рдЗрд╕рд╕реЗ xdbg рдХрд╛ рд╡рд┐рдХрд╛рд╕ %break )ред рддрдереНрдп рдпрд╣ рд╣реИ рдХрд┐ рдмреНрд░реЗрдХрдкреНрд╡рд╛рдЗрдВрдЯ рдХреЛ embed рдЗрди-рдкреНрд▓реЗрд╕ рдлрд╝рдВрдХреНрд╢рди рдХреЛ рдХреЙрд▓ рдХрд░рдиреЗ рдХреЗ рдмрдЬрд╛рдп рдмрд╛рд╣рд░реА рд░реВрдк рд╕реЗ рд╕реЗрдЯ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ, рдЗрд╕рдиреЗ рдПрдХ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХреА рдЕрдиреБрдорддрд┐ рджреА рд╣реИ рдЬреЛ рд╕реНрдерд╛рдиреАрдп рдЪрд░ рдХреЗ рд╕рд╛рде рдЗрдирдореЗрдВ рд╕реЗ рдХрдИ рд╕рдорд╕реНрдпрд╛рдУрдВ рдХреЛ рд╕рдВрдмреЛрдзрд┐рдд рдХрд░рддрд╛ рд╣реИред

рдореИрдВ рд╡рд░реНрддрдорд╛рди рдореЗрдВ рдХреЛрд░ IPython рдХреЗ рд▓рд┐рдП рдПрдХ рд╕рдВрдХреАрд░реНрдг-рд▓рдХреНрд╖рд┐рдд рдмрдЧрдлрд┐рдХреНрд╕ рдХреЛ рдкреБрд▓-рдЕрдиреБрд░реЛрдз рдХрд░рдиреЗ рдХреА рдпреЛрдЬрдирд╛ рдирд╣реАрдВ рдмрдирд╛ рд░рд╣рд╛ рд╣реВрдВред рд╣рд╛рд▓рд╛рдБрдХрд┐, рдореБрдЭреЗ рдпрд╣ рдЬрд╛рдирдиреЗ рдореЗрдВ рдмрд╣реБрдд рджрд┐рд▓рдЪрд╕реНрдкреА рд╣реИ рдХрд┐ IPython рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдФрд░ рджреЗрд╡ рд╕реНрдерд╛рдиреАрдп рдХреЛрдб рдирд┐рд░реАрдХреНрд╖рдг рдХреЗ рд▓рд┐рдП рдбрд┐рдмрдЧрд░-рдкреНрд░реЗрд░рд┐рдд рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдХреНрдпрд╛ рд╕реЛрдЪрддреЗ рд╣реИрдВред IPython (рдФрд░ рдЕрдм рднреА Jupyter) рдХрд╛ Python рдореЗрдВ рдЗрдВрдЯрд░реЗрдХреНрдЯрд┐рд╡ рдХреЛрдбрд┐рдВрдЧ рдХрд░рдиреЗ рдХреА рдХреНрд╖рдорддрд╛ рдкрд░ рдмрд╣реБрдд рдмрдбрд╝рд╛ рдкреНрд░рднрд╛рд╡ рдкрдбрд╝рд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдЕрднреА рднреА рдХрдИ рд╕реБрдзрд╛рд░ рдХрд┐рдП рдЬрд╛рдиреЗ рд╣реИрдВ рдХрд┐ рдпрд╣ рдХреИрд╕реЗ рдХрдХреНрд╖рд╛рдУрдВ/рдХрд╛рд░реНрдпреЛрдВ/рдореЙрдбреНрдпреВрд▓ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рднрд╛рд░реА рдПрдирдХреИрдкреНрд╕реБрд▓реЗрд╢рди рдХреЗ рд╕рд╛рде рдЗрдВрдЯрд░реИрдХреНрдЯ рдХрд░рддрд╛ рд╣реИред

рдореИрдВ рдЗрд╕ рдмрдЧ рд╕реЗ рдХрдИ рдмрд╛рд░ рдЬрд▓ рдЪреБрдХрд╛ рд╣реВрдВред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП

[mcgibbon<strong i="6">@xps13</strong>:~]$ cat test.py 
x = 1
def func():    
    x = 2
    import IPython
    IPython.embed()

if __name__ == "__main__":
    func()
[mcgibbon<strong i="9">@xps13</strong>:~]$ python test.py 
Python 3.7.6 (default, Dec 18 2019, 19:23:55) 
Type 'copyright', 'credits' or 'license' for more information
IPython 7.12.0 -- An enhanced Interactive Python. Type '?' for help.
In [1]: [x for _ in range(2)]                                                                                                                                                                                                                 
Out[1]: [1, 1]  # lol whoops. looked up in wrong scope.

рдореБрдЭреЗ рдпрдХреАрди рдирд╣реАрдВ рд╣реИ рдХрд┐ рдХреНрдпрд╛ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдореИрдВ рдЧрд╛рдирд╛ рдмрдЬрд╛рдиреЗрд╡рд╛рд▓реЛрдВ рдореЗрдВ рдЕрдкрдиреА рдЖрд╡рд╛рдЬ рдЬреЛрдбрд╝ рд░рд╣рд╛ рд╣реВрдВред

https://bugs.python.org/issue13557 рдХреЗ рдЖрдзрд╛рд░ рдкрд░ рдФрд░ рддрдереНрдп рдпрд╣ рд╣реИ рдХрд┐ рд╕реНрдкрд╖реНрдЯ рд░реВрдк рд╕реЗ рд╕реНрдерд╛рдиреАрдп () рдФрд░ рдЧреНрд▓реЛрдмрд▓реНрд╕ () рдХреЛ рдПрдХ рдирд┐рд╖реНрдкрд╛рджрди рдореЗрдВ рдкрд╛рд╕ рдХрд░рдирд╛ рдХреЗ рдмрдЧ рдХреЗ рдкреБрдирд░реБрддреНрдкрд╛рджрди рдХреЛ рдареАрдХ рдХрд░рддрд╛ рд╣реИ, рдРрд╕рд╛ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдЗрд╕реЗ рдареАрдХ рдХрд░рдирд╛ рд╕рдВрднрд╡ рд╣реИ IPython рд╕рд╣реА рд╕реНрдерд╛рдиреАрдп рдФрд░ рд╡реИрд╢реНрд╡рд┐рдХ рдирд╛рдо рд╕реНрдерд╛рди рдкрд╛рд╕ рдХрд░рдХреЗред

x = 1

def func():    
    x = 2
    exec("def g():\n print(x)\ng()")  # prints 1 :(
    exec("def g():\n print(x)\ng()", locals(), globals())  # prints 2 yay!


if __name__ == "__main__":
    func()
рдХреНрдпрд╛ рдпрд╣ рдкреГрд╖реНрда рдЙрдкрдпреЛрдЧреА рдерд╛?
0 / 5 - 0 рд░реЗрдЯрд┐рдВрдЧреНрд╕

рд╕рдВрдмрдВрдзрд┐рдд рдореБрджреНрджреЛрдВ

lewisacidic picture lewisacidic  ┬╖  3рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ

ghost picture ghost  ┬╖  4рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ

jakirkham picture jakirkham  ┬╖  4рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ

RinaldoB picture RinaldoB  ┬╖  3рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ

frenzymadness picture frenzymadness  ┬╖  3рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ