Не получается пищать PC спикером из python

Пытаюсь пищать в linux из скрипта Pyton. Сразу оговорюсь - системная утилита beep отлично пищит - т.е. спикер живой, система о нём знает. делаю по образу и подобию исходника beep.c из пакета busybox но уже на питоне:

#!/usr/bin/python
import os
import fcntl
import time

KIOCSOUND = 0x4B2F
CLOCK_TICK_RATE = 1193180

def beep(hz, len):
    fd = os.open("/dev/console", os.O_WRONLY)
    try:
        fcntl.ioctl(fd, KIOCSOUND, int(CLOCK_TICK_RATE / hz))
        try:
            time.sleep(len)
        finally:
            fcntl.ioctl(fd, KIOCSOUND, 0)
    finally:
        os.close(fd)

if __name__ == '__main__':
    beep(440, 0.5)

и получаю ошибку:

fcntl.ioctl(fd, KIOCSOUND, int(CLOCK_TICK_RATE/hz))
OSError: [Errno 25] Not a tty

пока вывернулся - запуская процесс beep. Но это как-то не красиво. Что я делаю не так в питоне?


Ответы (2 шт):

Автор решения: Sergey

Смотрим файл errno-base.h :

#define ENOTTY          25      /* Not a typewriter */

Т.е. 25-я ошибка - это ENOTTY. Смотрим man ioctl - что это за ошибка:

ENOTTY Указанный запрос не применяется к типу объекта, на который ссылается файловый дескриптор fd.

Это означает, что Ваша ioctl команда KIOCSOUND = 0x4B2F - не применима к данному устройству. Или Вы придумали эту команду, или данная реализация драйвера её не поддерживает.

→ Ссылка
Автор решения: Spider

В итоге всё получилось и заработало. Дело было действительно в /dev/console, а точнее в /dev/tty0. Как посоветовал @Fat-Zer глянул, что делает beep и обнаружил, что он после не удачной попытки с /dev/tty начинает перебирать по маске /dev/tty* и первый же отлично пищит. У меня решение под конкретную железку, поэтому пока жёсткое указание /dev/tty0 решило проблему.

→ Ссылка