Python скрипты для изменения файла hosts
Файл hosts используется операционной системой для сопоставления доменных имен с IP-адресами. Редактирование этого файла может потребоваться для блокировки или перенаправления трафика, тестирования серверов или локальной разработки. Python предоставляет удобные средства для автоматизации этой задачи, однако необходимо учитывать особенности разных ОС, права доступа и формат файла.
Основное решение: чтение и запись файла hosts построчно
Наиболее надежный способ - обработать файл как обычный текстовый файл, построчно проверить каждую строку и записать изменения. Это позволяет избежать повреждения структуры и сохранить комментарии.
import os
import sys
HOSTS_PATH = {
'win32': r'C:\Windows\System32\drivers\etc\hosts',
'linux': '/etc/hosts',
'darwin': '/etc/hosts'
}.get(sys.platform)
if not HOSTS_PATH:
raise OSError('Operating system not supported')
# Чтение существующего содержимого
try:
with open(HOSTS_PATH, 'r', encoding='utf-8') as f:
lines = f.readlines()
except PermissionError:
# На Windows требуется запуск от имени администратора, на Linux/macOS через sudo
print('Ошибка: нет прав на чтение файла. Запустите скрипт с повышенными привилегиями.')
sys.exit(1)
# Добавление новой записи, если её ещё нет
new_entry = '127.0.0.1 example.com'
entry_present = any(new_entry in line for line in lines if not line.strip().startswith('#'))
if not entry_present:
# Добавляем перед маркером 'localhost' или в конец
lines.append(f'{new_entry}\n')
# Запись изменений
with open(HOSTS_PATH, 'w', encoding='utf-8') as f:
f.writelines(lines)Python git bash (работа с git и bash в python)
Пояснение шагов:
- Определение пути к файлу в зависимости от ОС (Windows, Linux, macOS).
- Чтение всех строк с кодировкой UTF-8 (на старых Windows может быть ANSI, но UTF-8 чаще работает).
- Проверка наличия записи с учётом комментариев (строки, начинающиеся с #).
- Добавление записи и перезапись файла.
Типичные ошибки:
- PermissionError - недостаточно прав. Решение: запустить скрипт от администратора (Windows) или с sudo (Linux/macOS).
- UnicodeDecodeError - файл в другой кодировке (например, cp1251). Решение: открыть с ошибкой обработки
encoding='utf-8', errors='ignore'или определить кодировку черезchardet. - Неверное добавление - если добавить строку без символа новой строки, следующая операция может склеить записи. Всегда используйте
\n.
Как автоматически запрашивать права администратора на Windows?
Можно использовать модуль ctypes для запроса повышения привилегий. Если скрипт запущен без прав, он перезапускает себя с аргументом --admin. Пример:
if sys.platform == 'win32':
import ctypes
if not ctypes.windll.shell32.IsUserAnAdmin():
ctypes.windll.shell32.ShellExecuteW(
None, 'runas', sys.executable, ' '.join(sys.argv), None, 1)
sys.exit()Python host file (редактирование файла hosts)
Проблема: бесконечный перезапуск, если пользователь отказывает в правах. Решение - обработать возвращаемое значение ShellExecuteW (32 - успех, другие коды - ошибка).
Как использовать pathlib для работы с путями?
from pathlib import Path
hosts = Path('/etc/hosts')
content = hosts.read_text(encoding='utf-8')
# Изменяем содержимое
if '127.0.0.1 test.local' not in content:
with hosts.open('a', encoding='utf-8') as f:
f.write('127.0.0.1 test.local\n')
Python установка программы (установка программы на python)
Дополнительно: для добавления строки без проверки дубликатов используется режим 'a' (append).
Как временно редактировать hosts только для определённого процесса?
Этот вопрос выходит за рамки прямого редактирования файла. Можно использовать виртуальную сеть Docker или настройки прокси, но с файлом hosts такой трюк не работает.
Как добавить несколько записей из списка?
entries = ['10.0.0.1 app.local', '10.0.0.2 db.local']
with open(HOSTS_PATH, 'a', encoding='utf-8') as f:
for entry in entries:
f.write(f'{entry}\n')Ошибка: дублирование записей при повторном запуске. Решение - сначала прочитать и удалить старые совпадающие строки, а затем добавить новые.
Расширенные примеры работы с файлом hosts
1. Атомарная замена с резервным копированием
import shutil
from pathlib import Path
hosts = Path('/etc/hosts')
backup = hosts.with_suffix('.hosts.bak')
# Создаём резервную копию
shutil.copy2(hosts, backup)
# Читаем, редактируем, записываем во временный файл
temp = hosts.with_suffix('.tmp')
with hosts.open('r', encoding='utf-8') as src, temp.open('w', encoding='utf-8') as dst:
for line in src:
# Удаляем строки с определённым доменом
if 'example.com' in line:
continue
dst.write(line)
# Добавляем новую запись
dst.write('192.168.1.100 newserver.local\n')
# Атомарно заменяем оригинал
temp.replace(hosts)# После выполнения файл hosts обновлён, старый сохранён как /etc/hosts.bak
Преимущество: в случае сбоя, временный файл не повреждает оригинал.
2. Парсинг существующих записей в структуру данных
import re
parsed = []
with open(HOSTS_PATH, 'r', encoding='utf-8') as f:
for line in f:
stripped = line.strip()
if not stripped or stripped.startswith('#'):
continue
parts = re.split(r'\s+', stripped, maxsplit=2)
if len(parts) >= 2:
parsed.append({'ip': parts[0], 'hostnames': parts[1].split('#')[0].strip().split()})
print(parsed[:5])[{'ip': '127.0.0.1', 'hostnames': ['localhost']}, {'ip': '::1', 'hostnames': ['localhost', 'ip6-localhost', 'ip6-loopback']}]3. Удаление дублирующихся записей с сохранением комментариев
seen = []
new_lines = []
with open(HOSTS_PATH, 'r', encoding='utf-8') as f:
for line in f:
stripped = line.strip()
if not stripped or stripped.startswith('#'):
new_lines.append(line)
continue
# Нормализуем: приводим к нижнему регистру, убираем лишние пробелы
normalized = ' '.join(stripped.split())
if normalized.lower() not in seen:
seen.append(normalized.lower())
new_lines.append(line)
with open(HOSTS_PATH, 'w', encoding='utf-8') as f:
f.writelines(new_lines)# Файл очищен от повторяющихся строк, комментарии сохранены.
4. Работа с hosts на Windows через кодировку cp1251
import chardet
with open(r'C:\Windows\System32\drivers\etc\hosts', 'rb') as f:
raw = f.read()
encoding = chardet.detect(raw)['encoding'] or 'utf-8'
with open(r'C:\Windows\System32\drivers\etc\hosts', 'r', encoding=encoding) as f:
lines = f.readlines()
# ... изменения
with open(r'C:\Windows\System32\drivers\etc\hosts', 'w', encoding=encoding) as f:
f.writelines(lines)Примечание: модуль chardet необходимо установить отдельно (pip install chardet).
5. Скрипт с аргументами командной строки
import argparse
parser = argparse.ArgumentParser(description='Управление файлом hosts')
parser.add_argument('--add', nargs=2, metavar=('IP', 'HOST'), help='Добавить запись')
parser.add_argument('--remove', metavar='HOST', help='Удалить все строки с указанным хостом')
parser.add_argument('--list', action='store_true', help='Вывести активные записи')
args = parser.parse_args()
# Пример реализации функций...
print('Аргументы получены')> python hostctl.py --add 127.0.0.1 mytest Аргументы получены
6. Блокировка множества доменов по списку
block_domains = ['ads.com', 'tracker.net', 'spam.org']
redirect_ip = '0.0.0.0'
with open(HOSTS_PATH, 'r+', encoding='utf-8') as f:
data = f.read()
for domain in block_domains:
entry = f'{redirect_ip} {domain}\n'
if entry not in data:
f.write(entry)# При повторном запуске дублирование не происходит благодаря проверке вхождения строки.