Pergunta

Eu tenho pensado nisso por muito tempo e não tive nenhuma idéia, talvez alguns de vocês possam ajudar.

Eu tenho uma pasta de scripts python, todos os quais têm o mesmo corpo circundante (literalmente, eu o gerei de um script de concha), mas tenho um pedaço diferente de todos eles. Em outras palavras:

Top piece of code (always the same)
Middle piece of code (changes from file to file)
Bottom piece of code (always the same)

E percebi hoje que essa é uma má idéia, por exemplo, se eu quiser alterar algo das seções superior ou inferior, preciso escrever um script de shell para fazê -lo. (Não que seja difícil, parece que é muito ruim em termos de código).

Então, o que eu quero fazer é ter um script externo do Python que é assim:

Top piece of code
Dynamic function that calls the middle piece of code (based on a parameter)
Bottom piece of code

E então todos os outros arquivos Python na pasta podem ser simplesmente a peça do meio do código. No entanto, o módulo normal não funcionaria aqui (a menos que eu esteja enganado), porque eu receberia o código que preciso executar a partir do argumento, que seria uma string, e, portanto, eu não saberia qual função executar até o tempo de execução .

Então, pensei em mais duas soluções:

  1. Eu poderia escrever um monte de instruções if, uma para executar cada script com base em um determinado parâmetro. Eu rejeitei isso, pois é ainda pior que o design anterior.
  2. Eu poderia usar:

    OS.Command (sys.argv [0] scriptName.py)

    O que iria executar o roteiro, mas chamar Python para chamar Python não me parece muito elegante.

Então, alguém tem outras idéias? Obrigada.

Foi útil?

Solução

Se você souber o nome da função como uma string e o nome do módulo como uma string, então você pode fazer

mod = __import__(module_name)
fn = getattr(mod, fn_name)
fn()

Outras dicas

Outra solução possível é ter cada um de seus arquivos repetitivos importar a funcionalidade do arquivo principal

from topAndBottom import top, bottom
top()
# do middle stuff
bottom()

Além das várias respostas já publicadas, considere o Método do modelo Padrão de design: faça uma classe abstrata como

class Base(object):
    def top(self): ...
    def bottom(self): ...
    def middle(self): raise NotImplementedError
    def doit(self):
        self.top()
        self.middle()
        self.bottom()

Todo módulo flugable então faz uma aula que herda disso Base e deve substituir middle com o código relevante.

Talvez não seja justificado para este caso simples (você ainda precisa importar o módulo certo para instanciar sua classe e ligar doit nele), mas ainda vale a pena ter em mente (juntamente com suas muitas variações pitônicas, que expliquei amplamente em muitas negociações de tecnologia agora disponíveis no YouTube) para casos em que o número ou a complexidade de "peças flashes" continua crescendo - método de modelo (Apesar de seu nome horrível ;-) é um padrão sólido, bem comprovado e altamente escalável [[às vezes um pouco rígido demais, mas é exatamente isso que eu abordo nessas muitas conversas tecnológicas-e esse problema não se aplica a este específico use case]].

No entanto, o módulo normal não funcionaria aqui (a menos que eu esteja enganado), porque eu receberia o código que preciso executar a partir do argumento, que seria uma string, e, portanto, eu não saberia qual função executar até o tempo de execução .

Vai funcionar bem - use __import__ construído ou, se você tiver um layout muito complexo, criança levada módulo para importar seu script. E então você pode obter a função por module.__dict__[funcname] por exemplo.

Importar um módulo (como explicado em outras respostas) é definitivamente a maneira mais limpa de fazer isso, mas se por algum motivo isso não funcionar, desde que você não esteja fazendo nada muito estranho, você pode usar exec. Ele basicamente executa o conteúdo de outro arquivo como se fosse incluído no arquivo atual no ponto em que exec é chamado. É a coisa mais próxima que o python tem um source Declaração do tipo incluída em muitas conchas. No mínimo, algo assim deve funcionar:

exec(open(filename).read(None))

Que tal agora?

function do_thing_one():
   pass

function do_thing_two():
   pass

dispatch = { "one" : do_thing_one,
             "two" : do_thing_two,
           }

# do something to get your string from the command line (optparse, argv, whatever)
# and put it in variable "mystring"

# do top thing
f = dispatch[mystring]
f()
# do bottom thing
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top