Как я могу отключить новую функцию истории в Python 3.4?

Вопрос или проблема

Начиная с версии Python 3.4, все интерактивные команды записываются в файл ~/.python_history. Я не хочу, чтобы Python создавал или записывал в этот файл.

Создание символической ссылки на /dev/null не работает, Python удаляет файл и создает его заново. Документация предлагает удалить sys.__interactivehook__, но это также отключает автозавершение. Что следует сделать, чтобы отключить запись в файл истории, но при этом сохранить автозавершение?

Дополнительные детали:

Еще одно решение для ~/.pythonrc:

import readline
readline.write_history_file = lambda *args: None

С версии Python 3.6 вы можете использовать readline.set_auto_history, чтобы отключить это:

import readline
readline.set_auto_history(False)

Это работает для меня.

Создание файла ~/.pythonrc:

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)

Затем экспортируйте его:

export PYTHONSTARTUP=~/.pythonrc

Чтобы предотвратить запись Python в ~/.python_history, отключите хук, который активирует эту функциональность:

import sys
# Отключаем историю (...но также и автозавершение :/ )
if hasattr(sys, '__interactivehook__'):
    del sys.__interactivehook__

Если вы хотите включить автозавершение и отключить функцию истории, вы можете адаптировать код site.enablerlcompleter. Напишите следующий код в ~/.pythonrc и установите export PYTHONSTARTUP=~/.pythonrc в вашей оболочке, чтобы активировать его.

import sys
def register_readline_completion():
    # rlcompleter должен быть загружен для специфического для Python завершения
    try: import readline, rlcompleter
    except ImportError: return
    # Включаем автозавершение
    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

Мое текущее решение (для достаточно новых версий Python 3) предотвращает стандартное использование файла ~/.python_history, но оставляет возможность явной записи истории в заданный файл (с использованием readline.write_history_file(filename) или readline.append_history_file(…)), заключается в следующем коде в файле PYTHONSTARTUP:

import readline
import time

readline.add_history("# " + time.asctime()) # предотвращаем стандартное использование ~/.python_history
readline.set_history_length(-1) # неограниченно

Это имеет приятный (для меня) побочный эффект – маркировку любой явно записанной истории временем запуска интерпретатора. Это работает благодаря исправлению ошибки 5845, которое можно увидеть здесь.

Пока это не будет исправлено каким-либо образом в самом Python, вы можете сделать следующее в системах UNIX:

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

После этого вы будете получать

Ошибка в atexit._run_exitfuncs:

IsADirectoryError: [Errno 21] Является директорией

каждый раз, когда вы завершаете Python-оболочку. Код возврата все равно будет 0.

Обратите внимание, что если вы оставите это в виде файла, вам нужно будет создать и сделать не изменяемым другой файл, ~/.python_history

Положите следующее в файл и установите PYTHONSTARTUP на него (или назовите файл sitecustomize.py и сделайте его доступным из PYTHONPATH)

import readline
import atexit
import sys

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

Таким образом, у вас все еще будет доступ к автозавершению и предыдущей истории, но команды, которые вы вводите, не будут добавляться в файл истории.

Вот мой метод (который оказался в основном более надежной и питонической версией метода berdario). Он только отключает запись в .python_history, но не чтение из него, если он существует, или добавление новых строк в историю текущего экземпляра. Я рекомендую сохранить его как site-packages/sitecustomize.py, потому что site – это модуль, который как записывает в .python_history, так и импортирует sitecustomize, если он существует, хотя название другого и указание на него с помощью PYTHONSTARTUP тоже работает.

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

обновление: что я сделал для 3.7, специфично для моей системы, не pep8:

import rlcompleter,readline as r,sys
def f():r.parse_and_bind('tab:complete');r.read_init_file()
sys.__interactivehook__=f

Ответ или решение

Как отключить новую функцию истории в Python 3.4?

С момента обновления до Python 3.4, пользователей беспокоит автоматическое сохранение вводимых команд в файл ~/.python_history. Если вы хотите отключить это поведение, но при этом сохранить возможность автозаполнения (табуляции), ниже представлены несколько подходов, которые помогут вам решить эту задачу.

1. Использование файла ~/.pythonrc

Одним из простых способов отключить запись в файл истории является использование специального файла конфигурации для Python — ~/.pythonrc. Вам нужно будет создать этот файл, если он еще не существует, и добавить туда следующий код:

import readline
import atexit

# Укажите путь к вашему файлу истории
readline_history_file = os.path.join(os.path.expanduser('~'), '.python_history')

# Попытка загрузить существующую историю
try:
    readline.read_history_file(readline_history_file)
except IOError:
    pass  # Файл истории не существует

# Отключите автоматическую запись истории
readline.write_history_file = lambda *args: None

# Регистрация функции записи истории при выходе
atexit.register(readline.write_history_file, readline_history_file)

Дополнительно, вам нужно установить переменную окружения PYTHONSTARTUP, чтобы Python знал, что нужно загружать этот файл при старте:

export PYTHONSTARTUP=~/.pythonrc

2. Переопределение встроенного хуки

Если вы хотите еще больше настроить поведение, вы можете переопределить встроенный хук для интерактивного режима Python. Этот подход позволит вам отключить запись в файл истории, сохранив при этом возможность автозаполнения:

import sys
import readline

# Создаем новый хук для интерактивного режима
def new_interactive_hook():
    readline.set_auto_history(False)  # Отключение автоматической записи истории
    readline.parse_and_bind("tab: complete")  # Включение автозаполнения

# Установка нового хука
sys.__interactivehook__ = new_interactive_hook

Добавьте этот код в ваш файл ~/.pythonrc или новый файл sitecustomize.py в директорию site-packages.

3. Для более старых версий Python

Если вы используете более раннюю версию или хотите провести другие эксперименты, вы можете попробовать другой подход, создавая пустую директорию вместо файла .python_history. Это также поможет избежать проблем с записью в файл:

rm -f ~/.python_history  # Удалите существующий файл истории
mkdir ~/.python_history  # Создайте директорию с тем же именем
sudo chattr +i ~/.python_history  # Сделайте директорию неизменяемой

Этот метод приведет к ошибкам при попытке записи в директорию, но вы будете получать статус выхода 0.

Заключение

Каждый из предложенных способов имеет свои преимущества и недостатки. Выбор метода будет зависеть от ваших конкретных требований к настройкам окружения Python и предпочтений по удобству. Важно помнить, что все изменения следует вносить аккуратно, чтобы не нарушить функционирование других функций в интерактивном режиме Python.

Оцените материал
Добавить комментарий

Капча загружается...