Хэл Фултон - Программирование на языке Ruby
- Название:Программирование на языке Ruby
- Автор:
- Жанр:
- Издательство:ДМК Пресс
- Год:2007
- Город:Москва
- ISBN:5-94074-357-9
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Хэл Фултон - Программирование на языке Ruby краткое содержание
Ruby — относительно новый объектно-ориентированный язык, разработанный Юкихиро Мацумото в 1995 году и позаимствовавший некоторые особенности у языков LISP, Smalltalk, Perl, CLU и других. Язык активно развивается и применяется в самых разных областях: от системного администрирования до разработки сложных динамических сайтов.
Книга является полноценным руководством по Ruby — ее можно использовать и как учебник, и как справочник, и как сборник ответов на вопросы типа «как сделать то или иное в Ruby». В ней приведено свыше 400 примеров, разбитых по различным аспектам программирования, и к которым автор дает обстоятельные комментарии.
Издание предназначено для программистов самого широкого круга и самой разной квалификации, желающих научиться качественно и профессионально работать на Ruby.
Программирование на языке Ruby - читать онлайн бесплатно ознакомительный отрывок
Интервал:
Закладка:
system("notepad.ехе","myfile.txt") # Никаких проблем...
system("cmd /с dir","somefile") # 'dir' - встроенная команда!
Другое решение — воспользоваться библиотекой Win32API
и определить собственный вариант метода system
.
require "Win32API"
def system(cmd)
sys = Win32API.new("crtdll", "system", ['P'], 'L')
sys.Call(cmd)
end
system("dir") # cmd /с необязательно!
Таким образом, можно добиться более-менее системно-независимого поведения system
. Но если вы хотите запомнить выведенную программой информацию (например, в переменной), то system
— не лучший способ (см. следующий раздел).
Упомяну еще метод exec
. Он ведет себя аналогично system
с тем отличием, что новый процесс замещает текущий. Поэтому код, следующий за exec
, исполняться не будет.
puts "Содержимое каталога:"
exec("ls", "-l")
puts "Эта строка никогда не исполняется!"
14.1.2. Перехват вывода программы
Простейший способ перехватить информацию, выведенную программой, — заключить команду в обратные кавычки, например:
listing = `ls -l` # Одна строка будет содержать несколько строчек (lines).
now = `date` # "Mon Mar 12 16:50:11 CST 2001"
Обобщенный ограничитель %x
вызывает оператор обратных кавычек (который в действительности является методом модуля Kernel). Работает он точно так же:
listing = %x(ls -l)
now = %x(date)
Применение %x
бывает полезно, когда подлежащая исполнению строка содержит такие символы, как одиночные и двойные кавычки.
Поскольку обратные кавычки — это на самом деле метод (в некотором смысле), то его можно переопределить. Изменим его так, чтобы он возвращал не одну строку, а массив строк. Конечно, при этом мы создадим синоним старого метода, чтобы его можно было вызвать.
alias old_execute `
def `(cmd)
out = old_execute(cmd) # Вызвать исходный метод обратной кавычки.
out.split("\n") # Вернуть массив строк!
end
entries = `ls -l /tmp`
num = entries.size # 95
first3lines = %x(ls -l | head -n 3)
how_many = first3lines.size # 3
Как видите, при таком определении изменяется также поведение ограничителя %x
.
В следующем примере мы добавили в конец команды конструкцию интерпретатора команд, которая перенаправляет стандартный вывод для ошибок в стандартный вывод:
alias old_execute `
def `(cmd)
old_execute(cmd + " 2>&1")
end
entries = `ls -l /tmp/foobar`
# "/tmp/foobar: No such file or directory\n"
Есть, конечно, и много других способов изменить стандартное поведение обратных кавычек.
14.1.3. Манипулирование процессами
В этом разделе мы обсудим манипулирование процессами, хотя создание нового процесса необязательно связано с запуском внешней программы. Основной способ создания нового процесса — это метод fork
, название которого в соответствии с традицией UNIX подразумевает разветвление пути исполнения, напоминая развилку на дороге. (Отметим, что в базовом дистрибутиве Ruby метод fork
на платформе Windows не поддерживается.)
Метод fork
, находящийся в модуле Kernel
(а также в модуле Process
), не следует путать с одноименным методом экземпляра в классе Thread
.
Существуют два способа вызвать метод fork
. Первый похож на то, как это обычно делается в UNIX, — вызвать и проверить возвращенное значение. Если оно равно nil
, мы находимся в дочернем процессе, в противном случае — в родительском. Родительскому процессу возвращается идентификатор дочернего процесса (pid).
pid = fork
if (pid == nil)
puts "Ага, я, должно быть, потомок."
puts "Так и буду себя вести."
else
puts "Я родитель."
puts "Пора отказаться от детских штучек."
end
В этом не слишком реалистичном примере выводимые строки могут чередоваться, а может случиться и так, что строки, выведенные родителем, появятся раньше. Но сейчас это несущественно.
Следует также отметить, что процесс-потомок может пережить своего родителя. Для потоков в Ruby это не так, но системные процессы — совсем другое дело.
Во втором варианте вызова метод fork
принимает блок. Заключенный в блок код выполняется в контексте дочернего процесса. Так, предыдущий вариант можно было бы переписать следующим образом:
fork do
puts "Ага, я, должно быть, потомок."
puts "Так и буду себя вести."
end
puts "Я родитель."
puts "Пора отказаться от детских штучек."
Конечно, pid по-прежнему возвращается, мы просто не показали его.
Чтобы дождаться завершения процесса, мы можем вызвать метод wait
из модуля Process
. Он ждет завершения любого потомка и возвращает его идентификатор. Метод wait2
ведет себя аналогично, только возвращает массив, содержащий РМ, и сдвинутый влево код завершения.
Pid1 = fork { sleep 5; exit 3 }
Pid2 = fork { sleep 2; exit 3 }
Process.wait # Возвращает pid2
Process.wait2 # Возвращает [pid1,768]
Чтобы дождаться завершения конкретного потомка, применяются методы waitpid
и waitpid2
.
pid3 = fork { sleep 5; exit 3 }
pid4 = fork { sleep 2; exit 3 }
Process.waitpid(pid4,Process::WNOHANG) # Возвращает pid4
Process.waitpid2(pid3, Process::WNOHANG) # Возвращает [pid3,768]
Если второй параметр не задан, то вызов может блокировать программу (если такого потомка не существует). Второй параметр можно с помощью ИЛИ объединить с флагом Process::WUNTRACED
, чтобы перехватывать остановленные процессы. Этот параметр системно зависим, поэкспериментируйте.
Метод exit!
немедленно завершает процесс (не вызывая зарегистрированных обработчиков). Если задан целочисленный аргумент, то он возвращается в качестве кода завершения; по умолчанию подразумевается значение 1 (не 0).
pid1 = fork { exit! } # Вернуть код завершения -1.
pid2 = fork { exit! 0 } # Вернуть код завершения 0.
Методы pid
и ppid
возвращают соответственно идентификатор текущего и родительского процессов.
proc1 = Process.pid
fork do
if Process.ppid == proc1
puts "proc1 - мой родитель" # Печатается это сообщение.
else
puts "Что происходит?"
end
end
Метод kill
служит для отправки процессу сигнала, как это понимается в UNIX. Первый параметр может быть целым числом, именем POSIX-сигнала с префиксом SIG или именем сигнала без префикса. Второй параметр — идентификатор процесса-получателя; если он равен нулю, подразумевается текущий процесс.
Process.kill(1,pid1) # Послать сигнал 1 процессу pid1.
Process.kill ("HUP",pid2) # Послать SIGHUP процессу pid2..
Process.kill("SIGHUP",pid2) # Послать SIGHUP процессу pid3.
Process.kill("SIGHUP",0) # Послать SIGHUP самому себе.
Для обработки сигналов применяется метод Kernel.trap
. Обычно он принимает номер или имя сигнала и подлежащий выполнению блок.
Интервал:
Закладка: