para paquetes librerias libreria instalar descargar python ipython python-import rpyc

paquetes - Enganche la búsqueda de nombre global en un intérprete de python



instalar pip python windows (2)

Aquí está la cosa, tengo un proxy que contiene la referencia a un módulo remoto, y puse algunos de estos proxies a los sys.modules tal manera que puedo usarlos como módulos locales. Pero algunos otros objetos se colocan en el módulo __builtin__ en el entorno remoto (como una variable mágica para mayor comodidad de depuración o referencia). No quiero hacer referencia a estas vars como conn.__builtin__.var , y tengo que reemplazar el __builtin__ local (que parece no funcionar para reemplazar sys.modules[''__builtin__''] o para sys.modules[''__builtin__''] reglas de búsqueda de nombres globales. Cómo "Para un módulo, simplemente puede sobrecargar un getattr para hacer esto. Pero en un intérprete interactivo como IPython , ¿quién es el módulo principal o cómo hacerlo? Actualización: Como lo señaló @Nizam Mohamed, sí, puedo obtener el módulo __main__ , pero todavía no puedo modificar el nombre de la función de búsqueda de la misma.

Me gustaría convertir el entorno local completamente para que sea remoto (para una consola de depuración)

ACTUALIZAR

Por ahora, simplemente __builtin__.__dict__ todos los __builtin__.__dict__ y si hay un nombre que no está en el local __builtin__ . Agrego el nombre al local __builtin__ . Pero no es tan dinámico en comparación con una regla de búsqueda de nombres que dice: si no puedo encontrar el nombre en __builtin__ local, intente con el remoto.

here hay una discusión similar.

Y this pregunta da una simulación de módulo por reemplazarlo con un objeto en sys.modules . Pero esto no funcionará para la búsqueda de nombre __builtin__ , también traté de reemplazar la __builtin__.__getattribute__ con una personalizada que primero usará la búsqueda original seguida de una personalizada cuando falla. Pero la búsqueda de nombre global de __builtin__ nunca se __builtin__ en __builtin__.__getattribute__ incluso __builtin__.__getattribute__(''name'') devuelve el valor deseado, __builtin__.name o name nunca devuelve uno.


Usar la transformación AST del shell IPython

Como dijo @asmeurer, puede escribir un transformador AST simple para "enganchar" la búsqueda de nombre de variable. La clase base ast.NodeTransformer proporciona un método visit_Name que puede manipular. Solo necesita sobrecargar este método para redefinir las variables existentes en el módulo remoto pero no localmente.

El siguiente módulo se puede utilizar como una extensión de IPython :

testAST.py

import ast modName = "undefined" modAttr = [] user_ns = {} class MyTransformer(ast.NodeTransformer): def visit_Name(self, node): if node.id in modAttr and not node.id in user_ns: return self.getName(node) return node def getName(self, NameNode): return ast.Attribute(value=ast.Name(id=modName, ctx=ast.Load()), attr = NameNode.id, ctx = NameNode.ctx) def magic_import(self, line): global modName, modAttr, user_ns modName = str(line) if not self.shell.run_code( compile(''import {0}''.format(line), ''<string>'', ''exec'') ): user_ns = self.shell.user_ns modAttr = user_ns[line.strip()].__dict__ self.shell.ast_transformers.append(MyTransformer()) print modName, ''imported'' def load_ipython_extension(ip): ip.define_magic(''magic_import'', magic_import)

dummyModule.py

robot=" World"

Uso:

In [1]: %load_ext testAST In [2]: %magic_import dummyModule In [3]: print "Hello" , robot Hello World In [4]: dummyModule.robot_II = "Human" In [5]: print "Hi", robot_II Hi Human

El beneficio de este método es que cualquier modificación al módulo remoto surte efecto inmediatamente porque la búsqueda se realiza en el nivel de idioma y no se copia y almacena en caché ningún objeto.

Un inconveniente de este método es que no se puede manejar la búsqueda dinámica. Si eso es importante para ti, tal vez el enganche python_line_transforms sea ​​más adecuado.


Hay una manera de obtener una lista de todos los nombres que utilizará el módulo. Aunque no modifica el mecanismo de búsqueda, creo que resuelve tu problema.

Aquí hay un código (ojala que sea lo suficientemente comprensible) que puedes poner en un módulo, llamémoslo magic :

import sys def magic(): # Get the caller frame frame = sys._getframe().f_back # Unwind all internal Python import-related stuff while frame.f_code.co_filename.startswith(''<''): frame = frame.f_back importer = frame # Iterate through names the module has/will use for name in importer.f_code.co_names: # If the module has not yet defined/imported this name if name not in importer.f_globals and / name not in importer.f_locals and / name not in __builtins__: # Replace the name in the importer''s namespace # You''ll have to replace the right-hand side by your specific code importer.f_globals[name] = ''hello world''

Luego puedes importarlo para hacer magia:

import magic magic.magic() print(hi)

Sin embargo, hay dos desventajas. Primero, las búsquedas dinámicas fallarán:

import magic magic.magic() print(globals()[''hi'']) # KeyError: ''hi''

Aunque ese caso en particular puede resolverse mirando las cadenas en el importer.f_code.co_consts , no funcionará con búsquedas dinámicas más avanzadas como print(globals()[''h''+''i''])

El segundo inconveniente es que no funcionará en las funciones:

import magic magic.magic() def f(): print(hi) # NameError: name ''hi'' is not defined f()

Esto se debe a que, en ese caso, el nombre hi está en el f.__code__.co_names lugar de los co_names del módulo.

Una posible solución sería modificar la magic para intentar encontrar todas las funciones del módulo y modificar su código, pero no funcionará con las funciones definidas dentro de las funciones, etc.

Otra solución es llamar magic en la función:

import magic def f(): magic.magic() print(hi) f()