Ipython: Não é possível fazer blocos de código de várias linhas em ipython

Criado em 27 set. 2018  ·  26Comentários  ·  Fonte: ipython/ipython

Acabei de fazer pip install ipython enquanto estava dando uma aula hoje e digitei uma instrução if e, em seguida, apertei enter após a primeira linha e o código executado.

Isso parece um bug.

Eu fiz um pip install ipython==6.5.0 e apertando Enter em um bloco de código corretamente me mostrou a próxima linha recuada para digitar.

Estou no Ubuntu 18.04 executando ipython no tmux, embora duvide que o tmux seja o problema aqui.

Hacktoberfest help wanted

Comentários muito úteis

Na verdade, obtive uma regressão com minha correção. Consertando agora.

O PR # 11354 é atualizado agora.

Todos 26 comentários

você pode usar ctrl-o para forçar uma nova linha.

Eu nunca teria adivinhado esse. Não tenho certeza de como deixar isso mais claro, mas acho que merece alguns esclarecimentos / cuidados. Tentei todos os atalhos que pude pensar e acabei forçando um downgrade para corrigir meu problema.

Eu uso IPython para facilitar a digitação e edição de blocos multilinhas no REPL enquanto ensino audiências ao vivo. Suspeito que outras pessoas na minha situação possam ter problemas semelhantes.

Talvez um aviso em algum lugar que indica que Ctrl-O pode ser usado para fazer um bloco de código de várias linhas? Não tenho certeza se existe um lugar apropriado para isso.

É um bug com uma refatoração recente, eu estava apenas tentando dizer que você pode usar Ctrl-O enquanto isso se quiser usar 7.x

Ah ótimo! Estou feliz que foi apenas um bug. Obrigado @Carreau! 😄

Você se importaria de me dar alguns exemplos (funcionando e não funcionando) do que você espera, a fim de fornecer teste para as correções?

Eu tenho alguns, mas apenas coletando alguns e não quero influenciá-lo.

with open('hello.txt', mode='wt') as my_file:
    my_file.write('hi')
    my_file.write('hi again')

Não consigo me lembrar do segundo exemplo, mas vários loops:

numbers = [2, 1, 3, 4, 7, 8, 11]

for n in numbers:
    if n > 0:
        print(n*2)
    else:
        print(n/2)

@Carreau está trabalhando neste assunto? Eu ficaria feliz em ajudar

oi @Deborah-Digges, dei uma olhada rápida, mas não muito até agora.

Eu escrevi este pequeno caso de teste para ver a diferença entre o antigo input_splitter e o novo input_transformer:

from IPython.core import inputtransformer2 as ipt2 # new way
from IPython.core import inputsplitter #oldl way

occ =  inputsplitter.InputSplitter().check_complete
cc = ipt2.TransformerManager().check_complete

comp = lambda x : (cc(x), occ(x), x)
print(comp('if'))
print(comp('if\n\n'))
print(comp("""
def foo():
    print('Hello')"""
))
print(comp('if True:'))

Qual resultado em

(('invalid', None), ('invalid', None), 'if')
(('complete', None), ('invalid', None), 'if\n\n')
(('complete', None), ('incomplete', 4), "\ndef foo():\n    print('Hello')")
(('incomplete', 4), ('incomplete', 4), 'if True:')

Você vê que o 3º item é o que nos interessa. O segundo foi por curiosidade, já que um dos "recursos" do IPython é forçar a execução se houver mais de 2 novas linhas.

Parte do código relevante está em shortcut.py:L109-L127 .

Eu acho que há algum tipo de conflito entre o papel de definir se uma verificação de código está "completa" ou se devemos "executar ou adicionar uma nova linha".

_Estou supondo_ que a heurística que verifica se a entrada é multilinha e se o último caractere já é uma linha nova ou não deve ser suficiente.

Uma das questões restantes é onde colocar essa correção?

  • em shortcut.py ? em caso afirmativo, só corrigirá IPython do terminal
  • em input_transformer2? Acho que essa pode ser a solução certa, mas provavelmente também afetará o QtConsole.

Deixe-me saber se isso é suficiente para, pelo menos, você começar.

Obrigado !

Oi @Carreau ! Muito obrigado pela explicação detalhada e casos de teste.

Consegui reproduzi-lo localmente com a versão dev do ipython e agora começarei a examinar o código de shortcut.py e inputtransformer .

Você se importaria de me dar alguns exemplos (funcionando e não funcionando) do que você espera, a fim de fornecer teste para as correções?

Você não precisa de alguns exemplos. O bug ocorre de forma bastante reproduzível.
Multiline funciona apenas se a linha terminar em dois pontos. Se não houver dois pontos no final da linha, o iPython executa o código. Isso parece um pouco mais trivial com essas informações, mas nunca olhei para o código-fonte do iPython, então talvez eu esteja um pouco otimista demais aqui;)

iPython

Letras maiúsculas, por favor, não queremos problemas com maçã.

Você não precisa de alguns exemplos

Bem, não, eu não _preciso_, mas quero vários exemplos. Posso reproduzir e ter uma ideia de como consertar, mas ter vários casos me ajuda a ter certeza de que não estou atingindo um caso extremo. Eu tenho uma visão tendenciosa sobre como usar o IPython, então exemplos de outros são úteis.

iPython
Letras maiúsculas, por favor, não queremos problemas com maçã.

Pelo menos descobri porque havia o I superior no nome, obrigado e desculpe :)

Como um pedido de desculpas, aqui está uma solicitação de pull # 11354 que corrige este problema (principal). IMHO, este é um bug de bloqueio para IPython, você deve considerar fazer um lançamento em breve (veja quantos problemas são criados no github pelos usuários em relação a ele).

Pelo menos descobri porque havia o I superior no nome, obrigado e desculpe :)

Esse não é o (único) motivo, já que o IPython 0.1 foi lançado antes do primeiro iProduct, mas geralmente as pessoas se lembram

Como um pedido de desculpas, aqui está uma solicitação de pull # 11354 que corrige este problema (principal).

obrigado vou dar uma olhada quando o tempo permitir

você deve considerar fazer um lançamento em breve

Sim, assim que um voluntário tiver tempo, faremos isso. Há outro problema crítico, como lançar o jupyter_console, e não acho que alguém aqui consiga gastar algumas horas em $ DAYJOB para fazer isso. Portanto, pode ter que esperar por este fim de semana.

Na verdade, obtive uma regressão com minha correção. Consertando agora.

Na verdade, obtive uma regressão com minha correção. Consertando agora.

O PR # 11354 é atualizado agora.

Obrigado pela correção, alguma idéia de quando isso será lançado? Estou usando atalhos de teclado do vim para CTRL-O não funcionar para mim (ESC + o funciona ...)

Obrigado pela correção, alguma idéia de quando isso será lançado?

Esse será um dos voluntários do projeto que terá algumas horas livres para fazer a triagem dos poucos problemas restantes do 7.1 e fará um lançamento. Espero ter talvez algumas horas neste fim de semana, mas isso pode não ser suficiente.

Qualquer ajuda na triagem / revisão / marcação dos PRs / problemas existentes seria útil.

Ainda reproduzível com os blocos async with , tentei o branch master atual e a v7.1.1 do PyPI.

In [16]: async with aiofiles.open('/tmp/foobar', 'r') as f:
    ...:     content = await f.read()

In [17]: content
Out[17]: 'hello'

Hum, provavelmente é uma interação estranha com autoawait.

Oh, eu não achei que isso fosse relacionado a esse problema. De qualquer forma, a razão disso é que quando temos

async with aiohttp.ClientSession() as session:
    pass|   # < cursor is there

ele executa check_complete em cada final de linha, que, por sua vez, executa compile_command , e o último gera SyntaxError porque 'async with' é usado fora da função async .
No meu garfo, acabei de silenciar SyntaxError mas certamente não é a maneira mais brilhante de consertar isso, lol.

Soluções / ideias possíveis:

  • deve verificar se autoawait está ligado. se for, poderia ignorar aquele caso SyntaxError . Não acho que seja uma boa solução, mas talvez também esteja complicando as coisas.

  • se o autoawait estiver ativado, alimente compile_command() com o código empacotado com _asyncify() . Acho que desta forma não aumentará SyntaxError , mas não tenho certeza se o problema de nova linha será resolvido porque _asyncify() si adiciona alguns níveis de recuo e pode facilmente ficar confuso.

  • talvez _AsyncSyntaxErrorVisitor possa ajudar alguém? Mas eu acho que é o contrário

Sinto muito pela falta de dedicação, gostaria de enviar o PR, mas odeio escrever testes e outras coisas e também não tenho certeza da melhor maneira de consertar isso. Mas espero que ainda seja útil para alguém.

Poderíamos tentar algo parecido com isso também.

Esse é o seu ponto nº 2, e é realmente feio. A nova linha funciona. O que seria bom é obter suporte adequado em CPython.

Este problema ainda não foi resolvido? Acho que posso ter pegado esse bug ...

Isso aconteceu hoje pela primeira vez (durante uma demonstração com um cliente quando eu estava tentando demonstrar o que é um gerador em Python !!!).

Estou fazendo algo errado ou o que devo fazer para escrever blocos de código de várias linhas (além da solução alternativa CTRL-o)?

Resultado esperado conforme demonstrado no Python REPL padrão:

(tsa) BillsMacBookPro:develop billtubbs$ python
Python 3.5.5 | packaged by conda-forge | (default, Jul 23 2018, 23:45:11) 
[GCC 4.2.1 Compatible Apple LLVM 6.1.0 (clang-602.0.53)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> for i in range(5):
...     x = i*2
...     print(x)
... 
0
2
4
6
8
>>> exit()

Resultado hoje quando eu digito o mesmo em um REPL do iPython:

(tsa) BillsMacBookPro:develop billtubbs$ ipython
Python 3.5.5 | packaged by conda-forge | (default, Jul 23 2018, 23:45:11) 
Type 'copyright', 'credits' or 'license' for more information
IPython 7.0.1 -- An enhanced Interactive Python. Type '?' for help.

In [1]: for i in range(5): 
   ...:     x = i*2                                                                   

In [2]:      

O iPython REPL recua automaticamente a segunda linha conforme o esperado. Mas quando eu digito enter no final da segunda linha, ele executa as duas linhas em vez de fornecer uma terceira linha opcional.

Conforme descrito acima, posso obter o resultado desejado pressionando CTRL-o em vez de pressionar Enter na segunda linha:

In [2]: for i in range(5): 
   ...:     x = i*2 
   ...:     print(x)                                                                  
0
2
4
6
8

IPython 7.0.1 - ...

Atualize seu IPython, este problema está resolvido, ainda há um caso extremo com código assíncrono.

Oh, desculpe. Eu pensei que eu fiz. Depois de conda update ipython eu recebo # All requested packages already installed.

Desculpe, estou um pouco confuso. Qual é a versão mais recente e como faço a atualização para ela?

Dependerá de como você o instalou, sugiro tentar com pip install para ver se funciona. Mas você também pode estar trabalhando em um ambiente.

Quando coisas assim acontecem, tento desinstalar agressivamente até não conseguir iniciar o IPython e reinstalar.

Esta página foi útil?
0 / 5 - 0 avaliações