• Revista PROGRAMAR: Já está disponível a edição #53 da revista programar. Faz já o download aqui!

magician

Criar Classes ou Modules on the fly

27 mensagens neste tópico

Boas preciso de criar uma classe em python mas de forma "on the fly" ou seja em runtime e dinâmica, o Java tem recursos baseados em Reflection para esse efeito. Já pesquisei sobre python que também parece ter recursos para efeitos semelhantes em runtime mas não encontrei o que preciso, que é mesmo criar uma classe :\ Alguém me poderia ajudar ?

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

O que é uma class "on the fly"?

Desculpem a ignorância, mas por este nome não vou lá :x

É algo deste género?

class pessoa:
    pass
toni = pessoa()
toni.idade = 25
toni.altura = 175

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

lol é normal os espanto xD não é algo muito usado.

Vou dar o exemplo em Java pk não sei como funciona em python

O java permite a um Objecto Class adicionar métodos, editar, etc... com as suas limitações claro, permite ainda criar uma class a partir de uma array de bytes.

O que quero é criar uma classe nem a ter de escrever, ou seja quando o programa está a correr, com base e respostas enviadas do servidor, tipo a classe tem este método e aquele e tal.

Basicamente é criar uma classe em runtime e instanciala como se estive-se em ficheiro.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Basicamente o que quero é algo tipo isto

FileInputStream in = new FileInputStream( "Hello.class" );

byte [] b = new byte [in.available()]; 

in.read(b);

Class c = new NetworkClass().loadClasse("Hello", b);

Object o = c.newInstance();

((Hi)o).printHello("asa");

o "Hi" é o interface implementado pela classe Hello.

Neste caso a classe existe em ficheiro, mas poderia ser enviada por socket e assim nem precisar de estar no programa em si.

Ou seja um programa descentralizado.

Acho que python não tem este recurso de converter um byte [] em uma classe ou module, existem um modulo que permite criar um objecto module limpo on the fly, depois não encontro é forma de "injectar" o conteúdo do modulo lá para dentro. :\

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Pá, a única forma que estou a ver fazer isso é com eval() ou import. Isto é, no caso de teres no ficheiro o código mesmo.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Hmm, acho que estou a perceber, o que tu queres é guardar a estrutura de dados (numa variavel) e depois usa-la, certo?

Acho que sei como o fazer, dá-me uns minutos.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Sim mais ou menos isso quero ter uma classe "virtual", imagina que tem um programa que precisa de determinada classe para funcionar, e tens um servidor que ao ser feito um pedido ele envia a classe por um socket, nomeadamente por um byte [] ou assim, depois cabe ao cliente converter esses dados na classe mas sem ser fisicamente, sem precisar de ter um ficheiro propriamente dito.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Sim mais ou menos isso quero ter uma classe "virtual", imagina que tem um programa que precisa de determinada classe para funcionar, e tens um servidor que ao ser feito um pedido ele envia a classe por um socket, nomeadamente por um byte [] ou assim, depois cabe ao cliente converter esses dados na classe mas sem ser fisicamente, sem precisar de ter um ficheiro propriamente dito.

Pois, é o que estava a pensar. Só estou a ver isso com import (precisas de ter um ficheiro na máquina para o poder importar, mas podes criá-lo a qq momento), ou com um eval().
0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Sim mais ou menos isso quero ter uma classe "virtual", imagina que tem um programa que precisa de determinada classe para funcionar, e tens um servidor que ao ser feito um pedido ele envia a classe por um socket, nomeadamente por um byte [] ou assim, depois cabe ao cliente converter esses dados na classe mas sem ser fisicamente, sem precisar de ter um ficheiro propriamente dito.

Ok, vou ver se consigo fazer isso.
0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Pois mas a ideia é não ter nada fisicamente lol ser mesmo tudo virtual. Conseguir enviar e utilizar uma classe sem ter ou usar o ficheiro correspondente :\

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Encontrei uma solução, usando o modulo imp http://www.python.org/doc/2.5.2/lib/module-imp.html

>>> import imp
>>> a = open("teste1.txt", "r")
>>> xpto = imp.load_module("teste", a, "", ('', 'r', imp.PY_SOURCE))
>>> dir(xpto)
['__builtins__', '__doc__', '__file__', '__name__', 'b', 'teste']
>>>  dir(xpto.teste)
['__doc__', '__module__', 'a']
>>> 

O a pode ser um file handler ou um socket salvo erro. O código do meu teste1.txt é:

class teste:
   a = 1

b = 2

Podes também importar bytecode, etc, dá uma olhada ao link que te dei do manual.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

É uma solução, se quiseres enviar o bytecode é usar PY_COMPILED em vez de PY_SOURCE. Eu estou a tentar fazer doutra maneira, mas não sei se vai resultar.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Humm parece funcionar, já tinha visto essa função mas nao tinha encontrado doc explicativa e ainda não me adaptei lá muito bem ao á forma da API do python lol Mesmo que não dê bem para o que quero acho que se devia meter isso na wiki ou aqui para consulta.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Essas classes são geradas no servidor remoto ou estão armazenadas em ficheiros?

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

São armazenadas em ficheiro no servidor.

Outra solução que pensei seria ter a classe definida em XML ou algo assim e depois o servidor criava a classe a partir das definições, mas não encontrei recursos.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Outra solução que pensei seria ter a classe definida em XML ou algo assim e depois o servidor criava a classe a partir das definições, mas não encontrei recursos.

Isso é simples de fazer. Tendo tudo definido em XML era cagativo, não tinha mesmo nada que saber. :D Either way, acho que era mais straight forward usar o imp com um socket. Experimentaste a ver se funciona?
0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Ainda não tive tempo, ando aqui de volta de outras coisas.

Já agora explica lá como fazias isso com XML é que não consegui fazer isso dessa forma.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Ainda não tive tempo, ando aqui de volta de outras coisas.

Já agora explica lá como fazias isso com XML é que não consegui fazer isso dessa forma.

Convertes o XML para um .py e depois é só importar...

Acho desisto da minha solução para o problema, tenho de ver melhor amanha... Anda à volta dos modulos pickle, shelve e marshal...

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Ainda não tive tempo, ando aqui de volta de outras coisas.

Já agora explica lá como fazias isso com XML é que não consegui fazer isso dessa forma.

Convertes o XML para um .py e depois é só importar...

Também é uma ideia. A ideia que tinha era teres um XML descritivo do objecto. Exemplo:

class teste:
    """Implementa uma class de teste composta por 2 variáveis e 3 métodos, um deles construtor."""
    x = 1
    y = "ois"
    def __init__(self, x):
        self.a = x
    def ois(self):
        return self.y
    def ahah(self):
        return self.x + 2

<object>
<info>
<name>teste</name>
<description>Implementa class blablabla</description>
</info>
<vars>
<x type="int">1</x>
<y type="str">ois</x>
</vars>
<methods>
<specials>
<init>self.a = x</init>
</specials>
<others>
<ois>return self.y</ois>
<ahah>return self.x + 2</ahaha>
</others>
</methods>
</object>

Para passar do XML para um python object tinhas um objecto vazio e uma função para o "compor":

class Object:
    pass

def parse(x):
    if x[0] == 'str':
        return str(x[1])
    if x[0] == 'int':
        return int(x[1])
    #isto retorna o return de uma função com nome x[0] passando como argumento x[1]

def create(desc, vars, methods):
    obj = Object() #
    obj.__doc__ = desc
    for var in vars: #vars = {'x': ['int', '1'], 'y': ['str': 'ois']}
        obj.set(var, parse(vars[var])) #isto é para trocar por algum código que defina obj.var como o retorno do parse()
    for method in methods:
        #esta parte precisa de trabalho (tava a pensar em usar eval ou lambda's pa isto), definindo algo tipo obj.method = lambda: codigo
    return obj

Isto é fruto de um pensamento deveras rápido, mas com algum search e tal considero fazível :D

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Humm gostei da ideia :D Criar um objecto e injectar os dados, mas não sei se isso dá. Funcionaria se fosse um objecto Class como acontece no Java e ai injectar as vars e os métodos, agora não sei se podes injectar métodos num objecto instanciado que no fundo é o que tens ai.

Mas acho que isso merece alguma investigação!!

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

http://www.python.org/doc/2.5.2/lib/module-pickle.html

Qual é a razão para complicar com XMHell?

Serialização é um ponto totalmente descartado para o que quero, alias não se encaixa minimamente por vários motivos.

Primeiro o que é serializado é um objecto instanciado e não a classe e em segundo mal mude um método na classe o objecto serializado vai ao ar xD lol

XMHell ?? lol por acaso curto bué XML não acho inferno nenhum xD

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

OK, já percebo o que queres. Algo do género Reflection do Java.

Mesmo assim, estar a criar um ficheiro XML com classes convertidas de Python, para depois converter para um ficheiro Python de novo? Sou o único que acha isso uma ideia muito idiota?

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

OK, já percebo o que queres. Algo do género Reflection do Java.

Podes dar-me umas luzes do que é isso?

Mesmo assim, estar a criar um ficheiro XML com classes convertidas de Python, para depois converter para um ficheiro Python de novo? Sou o único que acha isso uma ideia muito idiota?

Nop, somos 2, mas limitei-me a dizer o que pediram. :D Para o que ele quer, a solução do imp parece-me o melhor.
0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Crie uma conta ou ligue-se para comentar

Só membros podem comentar

Criar nova conta

Registe para ter uma conta na nossa comunidade. É fácil!


Registar nova conta

Entra

Já tem conta? Inicie sessão aqui.


Entrar Agora