Может ли lua указать, вызван ли сценарий из другого файла? [dубликат]

Я бы просто создал массив массивов, где индекс равен значению i.

21
задан 23 December 2010 в 18:30
поделиться

7 ответов

Нет никакого «правильного» способа сделать это, так как Lua действительно не отличает код от того, откуда он пришел, это все просто функции. Тем не менее, это, по-видимому, работает в Lua 5.1:

  matthew @ silver: ~ $ cat hybrid.lua, если pcall (getfenv, 4), затем печатает («Библиотека») еще печатать (  «Основной файл») end matthew @ silver: ~ $ lua hybrid.lua Основной файл matthew @ silver: ~ $ lua -lhybrid Библиотека Lua 5.1.4 Copyright (C) 1994-2008 Lua.org, PUC-Rio & gt;  ^ C matthew @ silver: ~ $ lua Lua 5.1.4 Copyright (C) 1994-2008 Lua.org, PUC-Rio & gt;  требуют «гибридной» библиотеки & gt;  ^ C matthew @ silver: ~ $  

Он работает, проверяя, превышает ли глубина стека 3 (нормальная глубина для файла в интерпретаторе Lua на складе).

Я также включу эту (немного более портативную) альтернативу, хотя она делает еще больший скачок в эвристике, и даже в любых встроенных / настраиваемых конструкциях Lua. имеет случай сбоя (см. ниже):

  matthew @ silver: ~ $ cat hybrid2.lua function is_main (_arg, ...) local n_arg = _arg и #_arg или 0;  если n_arg == select ("#", ...), то для i = 1, n_arg do, если _arg [i] ~ = select (i, ...), тогда print (_arg [i], "не соответствует"  , (select (i, ...))) return false;  end end return true;  end return false;  end if is_main (arg, ...), затем print («Основной файл»);  else print («Библиотека»);  end matthew @ silver: ~ $ lua hybrid2.lua Основной файл matthew @ silver: ~ $ lua -lhybrid2 Библиотека Lua 5.1.4 Авторское право (C) 1994-2008 Lua.org, PUC-Rio & gt;  ^ C matthew @ silver: ~ $ lua Lua 5.1.4 Copyright (C) 1994-2008 Lua.org, PUC-Rio & gt;  требуется библиотека «hybrid2» & gt;   

Это работает, сравнивая содержимое _G.arg с содержимым «...». В основной части они всегда будут одинаковыми. В модуле _G.arg по-прежнему будут содержать аргументы командной строки, но «...» будет содержать имя модуля, переданное require (). Я подозреваю, что это ближе к лучшему решению для вас, учитывая, что вы знаете свое имя модуля. Ошибка в этом коде заключается в том, что пользователь выполняет основной скрипт с 1 аргументом, и это точное имя вашего модуля:

  matthew @ silver: ~ $ lua -i hybrid2.lua hybrid2  Lua 5.1.4 Авторское право (C) 1994-2008 Lua.org, PUC-Rio Основной файл & gt;  требуется «hybrid2» Main file & gt;   

Учитывая вышеизложенное, я надеюсь, что вы знаете, где вы стоите, даже если это не совсем то, что вы имели в виду:)

Обновление: для версии of hybrid.lua, который работает в Lua 5.1 и 5.2, вы можете заменить getfenv на debug.getlocal:

 , если pcall (debug.getlocal, 4, 1), затем напечатайте («Библиотека») еще  print («Основной файл») end  
13
ответ дан MattJ 15 August 2018 в 18:19
поделиться
  • 1
    Мне жаль, что я не мог бы продвигаться не один раз :-). Наверное, сейчас я буду придерживаться метода getfenv , поскольку он кажется меньшим. я определенно буду держать в голове другое решение. – user 24 December 2010 в 06:42
  • 2
    Кажется, что метод getfenv не работает в lua5.2 :( – coldfix 11 September 2013 в 18:14
  • 3
    @coldfix Я добавил некоторый модифицированный код, который, похоже, работает с 5.2. Остальная часть моего ответа все еще стоит, используйте на свой страх и риск :) – MattJ 11 September 2013 в 21:16
  • 4
    Это выглядит хорошо и намного более чистым / менее подверженным ошибкам, чем второй метод. Является ли соответствующий охват гарантией иметь хотя бы одну запись? Я опубликовал очень похожее решение, используя debug.getinfo вместо debug.getlocal , что делает ненужным использование pcall . С уважением, Томас – coldfix 11 September 2013 в 21:27
  • 5
    Да, возможно, debug.getinfo () был правильным подходом с самого начала. Однако я предполагаю, что я изначально пытался избежать в зависимости от библиотеки отладки, если мне не пришлось ... – MattJ 12 September 2013 в 22:56
 , если arg ~ = nil и arg [0] == string.sub (debug.getinfo (1, 'S'). source, 2) затем распечатайте «Основной файл», затем распечатайте «Library» end [  ! d1] 

Объяснение:

  1. Lua вызывает скрипт из интерпретатора с таблицей arg , с arg [0] - имя скрипта.
  2. Функция debug.getinfo возвращает таблицу информации, описывающую функцию на уровне стека, заданную его аргументом с номером ( 1 относится к функции, вызывающей getinfo ; 0 ​​относится к getinfo ). Его второй параметр не является обязательным: он определяет, какое подмножество полей getinfo извлекается. [!d]]
  3. Поле source таблицы, возвращаемое getinfo для файлов, содержит строку S . имя файла, в котором была определена функция, с префиксом @ . Передав значение этого поля в string.sub (..., 2) , мы разделим его на @ . (Поле short_src содержит имя без @ , но это потому, что оно определено как «удобное для печати» имя и менее безопасно, чем удаление источника [ ! d14].)

Обратите внимание, что этот код использует функцию debug , поэтому в 5.2 вам нужно будет потребовать отладки до быть в состоянии использовать его.

3
ответ дан coldfix 15 August 2018 в 18:19
поделиться
  • 1
    Следует отметить, что это имеет аналогичное падение, как ответ MattJ: Если arg определяется как глобальная переменная и содержит точно имя модуля, вы будете думать, что модуль вызывается как основной файл. – coldfix 11 September 2013 в 18:26

Возможно, вы можете иметь дело с библиотекой отладки с функцией debug.getinfo ()

 , если debug.getinfo (1) .what == "main" then - Main execution  end  

Для получения дополнительной информации см. справочное руководство.

1
ответ дан Faylixe 15 August 2018 в 18:19
поделиться
  • 1
    Отличная идея. К сожалению, это не сработает, поскольку код модуля также считается «основным». – coldfix 11 September 2013 в 18:04

Что случилось с этим:

  $ cat aa.lua #! / usr / bin / lua if (arg ~ = nil и arg [-1] ~ = nil), затем напечатать "  main "else print" library "end $ ./aa.lua main $ ./aa.lua arg1 arg2 main $ cat bb.lua #! / usr / bin / lua print (" in bb ") $ lua -laa bb.  lua library in bb $ lua Lua 5.1.4 Copyright (C) 1994-2008 Lua.org, PUC-Rio & gt;  требуется библиотека «aa» & gt;   
2
ответ дан sitaram chamarty 15 August 2018 в 18:19
поделиться
  • 1
    Проблема в arg может быть определена как глобальная переменная в вызывающем коде. Иначе это просто и здорово! – coldfix 11 September 2013 в 18:03

Когда Lua требует sa module, он передает ему имя, которое было требует d с помощью varargs ( ... ).

Итак, если ваш скрипт не намерен принимать какие-либо аргументы (из командной строки или иначе), вы можете использовать что-то вроде

 , если ... затем верните this_mod -  -module case else main () --main case end  

Обратите внимание, однако, что это не является надежным в (полностью) возможном случае, когда вы принимаете аргументы. Однако на этот момент вы можете совместить это с ответом Лукаша, чтобы получить:

 , если не package.loaded [...], тогда - главное дело else - конец кода конца  

Все еще не идеально (например, если скрипт вызывается с первым аргументом строки или именем какого-либо другого уже загруженного модуля), но, вероятно, достаточно хорош. В других ситуациях я откладываю ответ MattJ.

6
ответ дан Stuart P. Bentley 15 August 2018 в 18:19
поделиться
  • 1
    Второе предложение не работает в lua5.2. Запись package.loaded будет вставлена ​​только тогда, когда модуль вернется – coldfix 11 September 2013 в 18:23

Я использую lua 5.3 и имею проблемы с большинством предложений здесь. Это то, что сработало для моего использования:

  local my_module = {} ... если os.getenv ('CLI'), то main () else возвращает my_module end  

При запуске из командной строки я просто определил переменную среды, такую ​​как:

  CLI = 1 lua my_script.lua  

Работает для мне ™

0
ответ дан tpaul 15 August 2018 в 18:19
поделиться

вы можете попытаться проверить, требуется ли модуль.

из документации:

package.loaded Таблица, используемая требованием для управления, какие модули уже загружены , Если вам требуется модуль modname и package.loaded [modname] не является ложным, требуется просто вернуть сохраненное там значение.

С помощью этого вы могли бы написать:

  if not package.loaded ['modulename'] then main () end  
5
ответ дан Łukasz Gruner 15 August 2018 в 18:19
поделиться
  • 1
    что вам нужно будет узнать имя модуля ... arg [0] тоже не будет работать, поскольку модули lua сопоставляются после ?. lua;?. BIN (BIN - это расширение файла для родной библиотеки, например .so или .dll) – user 23 December 2010 в 18:44
  • 2
    Что вы пытаетесь достичь? Я предположил, что вы хотите поместить этот код в свой собственный модуль и знаете, как он будет называться. – Łukasz Gruner 23 December 2010 в 19:06
  • 3
    btw, arg [0] возвращает имя файла lua, который запускается, или который потребовал ваш модуль. try: test1.lua & gt; требуют "испытания" test.lua & gt; Печать (Arg [0]) – Łukasz Gruner 23 December 2010 в 19:07
  • 4
    & quot; btw, arg [0] возвращает имя lua-файла, который запускает & quot; - Я уже упоминал об этом в своем предыдущем комментарии ... – user 23 December 2010 в 19:25
  • 5
    Это не работает в lua5.2. Запись package.loaded будет вставлена ​​только после возвращения модуля. – coldfix 11 September 2013 в 18:05
Другие вопросы по тегам:

Похожие вопросы: