Вопрос или проблема
Начиная с версии Python 3.4, все интерактивные команды записываются в файл ~/.python_history
. Я не хочу, чтобы Python создавал или записывал в этот файл.
Создание символической ссылки на /dev/null
не работает, Python удаляет файл и создает его заново. Документация предлагает удалить sys.__interactivehook__
, но это также отключает автозавершение. Что следует сделать, чтобы отключить запись в файл истории, но при этом сохранить автозавершение?
Дополнительные детали:
- Дистрибутив: Arch Linux x86_64
- readline 6.3-3
- python 3.4.0-2
Еще одно решение для ~/.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.