Pergunta

Suponha que eu desenvolvi um utilitário usuário final de propósito geral escrito em Python. Anteriormente, eu tinha apenas uma versão disponível que foi adequado para Python posterior à versão 2.3 ou assim. Foi suficiente para dizer: "Download de Python se você precisa, em seguida, executar este script". Havia apenas uma versão do script no controle de origem (estou usando Git) para acompanhar.

Com Python 3, isto já não é necessariamente verdade. Para o futuro próximo, vou precisar para desenvolver simultaneamente duas versões diferentes, um adequado para Python 2.x e um adequado para Python 3.x. A partir de uma perspectiva de desenvolvimento, eu posso pensar em algumas opções:

  1. Manter dois roteiros diferentes no mesmo ramo, fazendo melhorias para ambos simultaneamente.
  2. Manter dois ramos separados, e mesclar comum muda e para trás como o desenvolvimento prossegue.
  3. Mantenha apenas uma versão do script, além de verificar em um arquivo de patch que converte o script de uma versão para a outra. Quando bastante mudanças foram feitas para que o patch não se aplica mais limpa, resolver os conflitos e criar um novo patch.

Atualmente, estou inclinado a opção 3, como os dois primeiros envolveria um monte de tédio propenso a erros. Mas a opção 3 parece confuso e meu sistema de controle de origem é suposto estar a gerir os patches para mim.

Para embalagem de distribuição, há mais opções para escolher:

  1. Oferecer dois pacotes de download diferentes, um adequado para Python 2 e um adequado para Python 3 (o usuário terá que saber baixar o correto para qualquer versão do Python que eles têm).
  2. Oferecer um pacote de download, com dois roteiros diferentes dentro (e, em seguida, o usuário tem que saber para executar o correto).
  3. Uma download do pacote com dois scripts específicos da versão, e um pequeno carregador de stub que pode ser executado em ambas as versões do Python, que executa o script correto para a versão Python instalado.

Novamente Atualmente, estou inclinado a opção 3 aqui, embora eu não tenha tentado desenvolver tal carregador de stub ainda.

Quaisquer outras ideias?

Foi útil?

Solução

Editar: minha resposta inicial foi baseado no estado de 2009, com o Python 2.6 e 3.0 como as versões atuais. Agora, com Python 2.7 e 3.3, há outras opções. Em particular, é agora bastante viável para usar uma única base de código para Python 2 e Python 3.

Portando Python Code 2 para Python 3

resposta Original:

O oficial recomendação diz:

Para portar Python 2.5 ou 2.6 existente código-fonte para Python 3.0, a melhor estratégia é a seguinte:

  1. (Pré-requisito :) Iniciar com excelente cobertura de teste.

  2. Port para Python 2.6. Este não deve ser mais trabalho do que o porto médio a partir do Python 2.x para Python 2. (x + 1). Certifique-se de todos os seus testes passar.

  3. (Ainda usando 2.6 :) Ligue a opção de linha de comando -3. Isso permite avisos sobre recursos que estarão removido (ou alteração) em 3,0. executar o seu conjunto de testes de novo, e código de correção que você receber avisos sobre até que haja sem avisos esquerda, e todos os seus testes ainda passar.

  4. Execute o 2to3 tradutor fonte-to-source sobre sua árvore de código fonte. (Veja 2to3 - Automated Python 2-3 Tradução código para saber mais sobre isso ferramenta.) Execute o resultado da tradução sob o Python 3.0. manualmente corrigir quaisquer problemas restantes, fixação problemas até que todos os testes passarem novamente.

Não é recomendado para tentar escrever código fonte que é executado sob inalterada tanto Python 2,6 e 3,0; você teria que usar um estilo de codificação muito contorcido, por exemplo. evitando declarações de impressão, metaclasses, e muito mais. Se você é manutenção de uma biblioteca que precisa apoiar tanto Python 2.6 e Python 3.0, a melhor abordagem é a de modificar o passo 3 acima, editando a 2,6 versão do código-fonte e funcionando o tradutor 2to3 novamente, em vez de editar a versão 3.0 da fonte código.

O ideal seria acabar com uma única versão, que é de 2,6 compatível e pode ser traduzido para 3,0 usando 2to3. Na prática, você pode não ser capaz de alcançar este objetivo completamente. Então você pode precisar de algumas modificações manuais para obtê-lo para trabalhar sob 3.0.

Gostaria de manter essas modificações em um ramo, como sua opção 2. No entanto, em vez de manter a versão final 3.0 compatível neste ramo, eu consideraria para aplicar as modificações manuais antes o 2to3 traduções, e colocar este 2.6 código modificado em seu ramo. A vantagem deste método seria a de que a diferença entre este ramo eo 2.6 tronco seria bastante pequeno, e só consistiria em alterações manuais, não as alterações feitas por 2to3. Desta forma, os ramos separados deve ser mais fácil de manter e merge, e você deve ser capaz de beneficiar de melhorias futuras no 2to3.

Como alternativa, apanhe um pouco de "esperar para ver" abordagem. Efectuar a sua portar apenas na medida em que você pode ir com uma única versão 2.6 além de tradução 2to3, e adiar a modificação manual restante até que você realmente precisa de uma versão 3.0. Talvez por esta altura, você não precisa de quaisquer ajustes manuais mais ...

Outras dicas

Para developement, a opção 3 é demasiado pesado. Manter dois ramos é a maneira mais fácil, embora a maneira de fazer isso irá variar entre VCSes. Muitos DVCS será mais feliz com repos separados (com um ancestral comum a ajuda fusão) e centralizados VCS provavelmente mais fácil trabalhar com com dois ramos. Opção 1 é possível, mas você pode perder algo para merge e um pouco mais IMO propenso a erros.

Para a distribuição, eu usaria a opção 3 e, se possível. Todas as 3 opções são de qualquer maneira válida e tenho visto variações sobre esses modelos de tempos em tempos.

Eu não acho que eu iria tomar este caminho em tudo. É doloroso do jeito que você olha para ele. Realmente, a menos que há um forte interesse comercial em manter ambas as versões ao mesmo tempo, isso é mais dor de cabeça do que ganho.

Eu acho que faz mais sentido para apenas manter a desenvolver para 2.x para agora, pelo menos por alguns meses, até um ano. Em algum ponto no tempo será apenas hora de declarar em uma versão final e estável para 2.x e desenvolver as próximas para 3.x +

Por exemplo, eu não vou mudar para 3.x até alguns dos principais marcos ir por esse caminho: PyQt, matplotlib, numpy, e alguns outros. E eu realmente não me importo se em algum momento eles param 2.x apoio e apenas começar a desenvolver para 3.x, porque eu vou saber que em um curto período de tempo eu vou ser capaz de mudar para 3.x também.

Gostaria de começar por migrar para o 2.6, que está muito perto de python 3.0. Você pode até querer esperar por 2,7, que será ainda mais perto de python 3.0.

E então, depois de ter migrado para o 2.6 (ou 2.7), eu sugiro que você simplesmente manter apenas uma versão do script, com coisas como "se Py3k: ... else: ..." nos lugares raros onde será obrigatório. Claro que não é o tipo de código de desenvolvedores de nós gosta de escrever, mas então você não precisa se preocupar com o gerenciamento de vários scripts ou filiais ou patches ou distribuições, que vai ser um pesadelo.

O que você escolher, verifique se você tem testes completos com cobertura de código 100%.

Boa sorte!

opção Qualquer que seja para o desenvolvimento é escolhido, questões mais potenciais poderiam ser aliviados com a unidade completa testes para garantir que as duas versões produzir correspondência da saída. Dito isto, a opção 2 parece mais natural para mim: aplicar as alterações de árvore de uma fonte para outra árvore de código é uma tarefa (a maioria) os sistemas de controle de versão foram projetados para - por que não tirar vantagens das ferramentas que eles fornecem para facilitar este

Para o desenvolvimento, é difícil dizer sem 'conhecer o seu público'. usuários de energia Python provavelmente não apreciam ter que baixar duas cópias do seu software ainda para uma base de usuários mais geral que deveria provavelmente 'apenas trabalho'.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top