NB! Проблема полностью решена в версии SPSS 14 с появлением в SPSS скриптов Python.

Суть проблемы

Скрипты могут быть вызваны из синтаксиса и наоборот. Однако важной особенностью здесь является параллельность (или асинхронность) выполнения вызванной программы. Так, например, синтаксис, вызывающий скрипт, не приостанавливается до окончания работы скрипта, а продолжает своё выполнение. При таком параллельном (несогласованном, асинхронном) исполнении этих двух процессов, возможно возникновение ошибок, если в ходе выполнения процессы должны обмениваться данными. Например, синтаксис может попытаться обратиться к результатам работы скрипта в то время, когда второй ещё выполняется (результаты отсутствуют). В некоторых случаях возникновение ошибок будет вовсе не очевидным и пользователь будет озадачен тем, что программа работает без видимых сбоев, но даёт неверные результаты! Таким образом, при комбинировании синтаксиса и скриптов нужно учитывать указанное обстоятельство и составлять программу соответствующим образом.

Ниже приводятся комментарии Кирилла Орлова по данному вопросу:

  1. «Отношения между синтаксисом и скриптом, когда одно из них запускает другое, являются особой программистской темой. Она может заинтересовать, скорее, продвинутых пользователей, так как только они будут писать код, предусматривающий совместную работу синтаксиса и скрипта.
  2. Так как синтаксис исполняется ядром системы (оно ответственно за всю статобработку и преобразования и называется «SPSS Processor»), а скрипт исполняется совсем другим агентом — оболочкой, ответственной за поведение графического интерфейса (меню, и т.п.), то они могут работать независимо, но могут и прислушиваться друг к другу. Этот вопрос встает, когда синтаксис запускает скрипт или скрипт запускает синтаксис. (Синтаксис запускает скрипт командой SCRIPT. Скрипт запускает синтаксис командой objSpssApp.ExecuteCommands strCommand или парой родственных команд.)
  3. Могут быть два режима работы синтаксиса и скрипта, когда одно запускает другое. Один режим — согласованный (synchronous, не следует понимать как «одновременный»), когда одно запускает другое и приостанавливается, ожидая, когда то закончит исполняться. Другой режим — параллельный (asynchronous, не следует понимать как «разновременный»), когда одно, запустив другое, продолжает работу как ни в чем не бывало.
  4. Уточнение: скрипт, запуская синтаксис, может работать с ним в согласованном или параллельном режиме (вы должны написать True или False после команды — см. пункт 2). Синтаксис, запуская скрипт, работает с ним только в параллельном режиме.
  5. Преимущество согласованного соисполнения в том, что, если скрипт и синтаксис обмениваются какой либо информацией (напр. входящими или результатами) во время соисполнения, она синхронизована по времени, и оттого не может произойти ни недоразумений, ни сбоев. Но согласованное соисполнение хотя надежно, медленнее; более того, оно не всегда возможно (см. в частности, см. пункт 4).
  6. Параллельное соисполнение не тратит время на простои. Но, в ситуации обмена информацией, имеют место вышеупомянутые недоразумения между синтаксисом и скриптом относительно «свежести», синхронизованности того, что передается.
  7. В своей книге SPSS Programming and Data Management и этой странице, посвященной «проблеме асинхронности», Левек разьясняет «недоразумения» асинхронности и обсуждает, как можно сделать, чтобы в режиме параллельного соисполнения добиться правильно обмена информацией между синтаксисом и скриптом».

Файлы для демонстрации проблемы

Эти синтаксис и скрипт использованы для демонстрации проблемы асинхронного исполнения в SPSS. (на основе вопроса из новостной группы SPSS от Kai Borgolte, 16.08.1999).

**** Синтаксис test.sps **** .

data list free / v1 to v3.
begin data
1 2 3
end data.

frequencies variables = v1.

* Следующей строкой вызываем скрипт, который должен создать файл test.inc, включающий команду: frequencies variables = v2
script 'c:\temp\test.sbs'.
* Затем мы запускаем этот синтаксис чтобы получить частотное распределение переменной v2.
include 'c:\temp\test.inc'.
* Удаляем этот файл, поскольку он больше не нужен.
erase file = 'c:\temp\test.inc'.

frequencies variables = v3.
' **** Скрипт c:\temp\test.sbs **** .

Sub Main

Open "c:\temp\test.inc" For Output As #1
Print #1, "frequencies variables = v2 ."
Close #1

'Сообщение пользователю, что скрипт работает и файл создан.
MsgBox "test.sbs работает, файл test.inc создан"

End Sub

Демонстрация проблемы

  • Сохраните вышеприведённый скрипт и синтаксис в c:\temp\. Первый раз, когда вы запускаете синтаксис…
    1. Выводятся частоты переменной v1;
    2. Получаем сообщение, что скрипт работает и файл test.inc записан;
    3. Частоты переменной v2 не выводятся;
    4. Выводятся частоты переменной v3.
  • When you look at the log, you will see that test.inc was not found and that, hence, it was not erased (since it did not exist when that line of syntax was executed).
  • Когда посмотрим в лог, увидим ,что «that test.inc was not found» (не был найден) и, следовательно, не был удалён (потому что на самом он не существовал когда выполнялась эта строка синтаксиса!). Однако, если загляните в директорию c:\temp, то увидите нужный файл. Он был создан после выполнения команды ERASE.
  • Теперь, если запустите синтаксис повторно, не удаляя файл test.inc вручную, программа сработает как и ожидалась, мы увидим таблички частот для всех 3 переменных.

Данный пример включает вызов скрипта из синтаксиса. Обратите внимание, что эта проблема также возникает и при вызове синтаксиса из скрипта.

Возможные решения

Версия 12 и ранее

Скрипт, написанный Fabrizio SyntaxScript, предназначен для решения проблемы. Однако в этом файле скрипт может уйти в бесконечный цикл, если в конце файла синтаксиса будут оставлены пробелы. Скорректированная версия (SyntaxScript2) избавляет нас от этой проблемы.

Удостоверьтесь, что test.sps загружен в активное окно синтаксиса, загрузите и выполните SyntaxScript2 и вы увидите, что синтаксис test.sps работает так, как и ожидалось. Таблицы построены для всех 3 переменных. Для регулярного вызова скрипта SyntaxScript2 удобно сделать кнопочку на панели инструментов, чтобы вызывать его одним нажатием. Очень просто.

У этого скрипта, конечно, существуют свои ограничения. В частности, когда один скрипт вызывает другой скрипт и передаёт ему аргумент, вызываемый скрипт должен использовать особый метод чтобы прочесть аргумент.

В некоторых случаях обойти проблему асинхронности позволяет программа, написанная Alexis-Michel Mugabushaka, которая находится в разделе VB-программы страницы скриптов.

Версия 13

Появление команды HOST, которая выполняет инструкции на уровне операционной системы, даёт новые пути обхождения проблемы асинхронности. См. второе издание книги «Программирование и управление данными в SPSS» (SPSS Programming and Data Management), которая свободно доступна для скачивания с веб-сайта

Версия 14 и позднее

Начиная с версии 14, в SPSS могут исполняться скрипты Питон (Python), они работают синхронно с файлом синтаксиса из которого вызваны. Таким образом, проблема сейчас решена. См. примеры синхронного выполнения Питон-скриптов: Адаптивный код.