Como posso desativar o novo recurso de histórico no Python 3.4?

10

Desde a atualização para o Python 3.4, todos os comandos interativos são registrados ~/.python_history. Não quero que o Python crie ou grave neste arquivo.

Criando um link simbólico para /dev/nullnão funciona, o Python remove o arquivo e o recria. A documentação sugere excluir sys.__interactivehook__, mas isso também remove o preenchimento de guias. O que deve ser feito para desativar a gravação desse arquivo de histórico, mas ainda preservar o preenchimento de guias?

Detalhes adicionais:

Lekensteyn
fonte
Você já tentou chowning para enraizar?
25414 goldilocks
@ goldilocks Eu não considero que uma solução aceitável, e nem está usando chattr. Estou procurando um único arquivo de configuração (usuário) ou variável de ambiente.
Lekensteyn
Ok, mas você já sabe que não existe uma solução aceitável desde que examinou a documentação.
Goldilocks
De fato, chmodé a solução sugerida pelos desenvolvedores python neste relatório de bug de algumas semanas atrás, embora também haja alguma menção a ~/.inputrcele (não existe man readline, BTW, exceto a função de biblioteca).
25814 goldilocks
@ goldilocks Sim, eu estava prestes a vincular esse relatório de erro. No inputrcentanto, eu não sei como usar e chmodtambém não funciona para mim; o arquivo é modificado de qualquer maneira (Arch Linux). Existe uma info inputrcpágina, mas geralmente não estou tão feliz com a leitura de páginas de informações, pois elas são difíceis de navegar.
Lekensteyn

Respostas:

7

No Python 3.6, você pode usar o readline.set_auto_history para desativar isso:

import readline
readline.set_auto_history(False)
Colin Watson
fonte
Isso é bom para o shell do Python, mas cuidado: ele não parece funcionar no ipython.
z0r 2/09/19
Isso desativa completamente a história. Pessoalmente, estou bem com o histórico sendo preservado em minha sessão de intérprete, mas não quero que meu histórico seja gravado em disco e preservado em todas as sessões.
jamesdlin
Não funciona Isso não impede que o arquivo seja salvo e, em vez disso, quebra o histórico durante a sessão. De qualquer forma, o Python silenciosamente ativa o "recurso" na próxima vez em que o executar.
Boann
5

Isso funciona para mim.

Criando ~/.pythonrcarquivo:

import os
import atexit
import readline

readline_history_file = os.path.join(os.path.expanduser('~'), '.python_history')
try:
    readline.read_history_file(readline_history_file)
except IOError:
    pass

readline.set_history_length(0)
atexit.register(readline.write_history_file, readline_history_file)

Em seguida, exporte-o:

export PYTHONSTARTUP=~/.pythonrc
cuonglm
fonte
Isso parece permitir a gravação de um arquivo de histórico em vez de desativá- lo se não me engano? A menos set_history_lengthque algo mágico? O preenchimento de tabulação é feito para funções, não para histórico.
Lekensteyn
@Lekensteyn: sim, o tamanho do histórico é igual a zero, para que nada seja gravado no arquivo de histórico. Ah, acho que você deseja preservar o comando entre as sessões.
cuonglm
2
Isso ainda faz ~/.python_historycom que seja gravado (verificado com PYTHONSTARTUP=$HOME/.pythonrc strace -e file,write -o /tmp/st python). Começo a pensar que não há como desativar isso, mas mantenha a conclusão da guia sem duplicar o código /usr/lib/python3.4/site.py.
Lekensteyn
AFAIK, não há como realmente desabilitá-lo.
cuonglm
2

Outra solução ~ / .pythonrc:

import readline
readline.write_history_file = lambda *args: None
Waxrat
fonte
Não sei por que isso não é mais votado. Isso é simples e suprime diretamente a gravação do arquivo de histórico em vez de desabilitar o histórico completamente.
jamesdlin
Essa foi a única correção que funcionou para mim. Obrigado.
Boann
1

Para impedir a gravação do Python ~/.python_history, desative o gancho que ativa essa funcionalidade:

import sys
# Disable history (...but also auto-completion :/ )
if hasattr(sys, '__interactivehook__'):
    del sys.__interactivehook__

Se você deseja ativar o preenchimento de guias e desativar o recurso de histórico, pode adaptar o site.enablerlcompletercódigo. Escreva o código a seguir ~/.pythonrce defina export PYTHONSTARTUP=~/.pythonrcno seu shell para habilitá-lo.

import sys
def register_readline_completion():
    # rlcompleter must be loaded for Python-specific completion
    try: import readline, rlcompleter
    except ImportError: return
    # Enable tab-completion
    readline_doc = getattr(readline, '__doc__', '')
    if readline_doc is not None and 'libedit' in readline_doc:
        readline.parse_and_bind('bind ^I rl_complete')
    else:
        readline.parse_and_bind('tab: complete')
sys.__interactivehook__ = register_readline_completion
Lekensteyn
fonte
0

Até que seja corrigido de alguma forma no próprio Python, você pode fazer isso nos sistemas UNIX:

rm ~/.python-history
mkdir ~/.python-history
sudo chattr +i ~/.python-history || sudo chflags simmutable ~/.python-history

Depois disso, você estará recebendo

Erro em atexit._run_exitfuncs:

IsADirectoryError: [Erro 21] É um diretório

toda vez que você encerra um shell python. O status de saída ainda será 0.

Observe que, se você o deixar como arquivo, precisará criar e tornar imutável outro arquivo, ~/.python_history

int_ua
fonte
0

Coloque o seguinte em um arquivo e defina PYTHONSTARTUP-o (ou chame o arquivo sitecustomize.pye torne-o acessível a partir de PYTHONPATH)

import readline
import atexit
import sys

sys.__interactivehook__()
atexit.unregister(readline.write_history_file)

Dessa forma, você ainda terá acesso ao preenchimento de guias e ao histórico anterior, mas os comandos inseridos não serão adicionados ao arquivo do histórico.

berdario
fonte
Isso não parece funcionar (Python 3.5.1 no Arch Linux), o arquivo de histórico ainda é gravado na saída, mesmo que o PYTHONSTARTUPscript seja realmente executado.
Lekensteyn
Acabei de testá-lo no meu Arch Linux vm e funciona bem: gist.github.com/berdario/640b3ab00b128fdf3338
berdario
0

Aqui está o meu método (que acabou por ser basicamente uma versão mais confiável e pitônica do método de berdario). Desativa apenas gravar .python_history, mas não ler, se existir, ou anexar novas linhas ao histórico da instância atual. Eu recomendo salvá-lo como site-packages/sitecustomize.py, porque siteé o módulo que grava .python_historye importa, sitecustomizese existir , embora nomear outra coisa e apontar para ela PYTHONSTARTUPtambém funcione.

import sys
oldhook = getattr(sys, '__interactivehook__', None)
if oldhook:
    def newhook():
        import readline, atexit
        oldhook()
        atexit.unregister(readline.write_history_file)
    sys.__interactivehook__ = newhook

update: o que fiz para o 3.7, específico do meu sistema, não o pep8:

import rlcompleter,readline as r,sys
def f():r.parse_and_bind('tab:complete');r.read_init_file()
sys.__interactivehook__=f
bebê aterro
fonte
Python 3.7.3. Não está funcionando. O histórico ainda está registrado.
Boann
0

Minha solução atual (para versões suficientes do Python 3) impede o uso padrão de ~ / .python_history, mas deixa a possibilidade de gravação explícita do histórico em um determinado arquivo (usando readline.write_history_file (nome do arquivo) ou readline.append_history_file (... )) deve ter o seguinte no arquivo PYTHONSTARTUP:

import readline
import time

readline.add_history("# " + time.asctime()) # prevent default use of ~/.python_history
readline.set_history_length(-1) # unlimited

Tem o efeito colateral agradável (para mim) rotular qualquer histórico explicitamente escrito com o tempo de inicialização do intérprete. Ele funciona devido à correção do bug 5845, que pode ser vista aqui .

Ron Kaminsky
fonte