6
$\begingroup$

In Python, the boilerplate line if __name__ == "__main__": defines a code block that should be executed when the code is run as a script, but not when imported as a module.

Is there a way to do this using Mathematica's .wls scripts?

To clarify, I want to designate part of my code to be run only when the script is run in an interactive session or from the command line (e.g. using wolframscript), but not when the code is imported into another notebook/script using Get or similar.

$\endgroup$
  • $\begingroup$ you could check if $ScriptCommandLine is {} $\endgroup$ – user42582 Oct 5 '18 at 13:28
  • $\begingroup$ $ScriptCommandLine == {} is the same as $Notebooks, as far as I can tell. It tells me if I'm running code from a front end (vs. a command line), not whether I'm running code directly from a notebook/script (vs. importing it). I added some clarification to the question. $\endgroup$ – Theelepel Oct 5 '18 at 14:40
  • $\begingroup$ Make sure those cells you don't want evaluated when the package loads do not have the property Initialization Cell $\endgroup$ – m_goldberg Oct 5 '18 at 15:52
  • $\begingroup$ $EvaluationEnvironment would be the solution but I do not know if it wors for scrips, it was quite buggy. $\endgroup$ – Kuba Oct 5 '18 at 19:29
  • 2
    $\begingroup$ Instead of relying on which mode the file is read via, why not just have the main[] function only evaluate if a certain global flag is set. When the file is read, if Global`$EvaluateFlag is not True, you don't run the main[] function. $\endgroup$ – Jason B. Oct 5 '18 at 20:14
2
$\begingroup$

You may be able to use $EvaluationEnvironment to check notebooks vs. Scripts.

If you are trying to check against whether it is the main file or not $Input may be useful. It should be set when Get-ing a file or similar. So the check If[$Input==="", ...] may work for you.

| improve this answer | |
$\endgroup$
  • $\begingroup$ Thanks, I think $Input is the best solution. $\endgroup$ – Theelepel Oct 15 '18 at 15:34
  • $\begingroup$ Warning: This works when running interactively, or when using wolframscript -file, or using ./script.wls with the shebang. But wolframscript -script script.wls sets the value of $Input to the path of the script. $\endgroup$ – Theelepel Nov 5 '18 at 14:03
4
$\begingroup$

This works on my Windows machine (not sure how well it translates to Mac and Linux yet):

Place this in a file called test.wls:

checks = { $Notebooks, Length[$CommandLine]===1, MemberQ[$CommandLine,"-wlbanner"], MemberQ[$CommandLine,"-noicon"] };
Print @ Switch[
 checks,
 {True,False,False,True}, "Running in notebook interface",
 {False,True,False,False}, "Running in wolfram.exe",
 {False,False,True,False}, "Running in wolframscript.exe",
 {False,False,False,False}, "Running in test.wls"
];

Then run this file in different modes. First as a script:

C:\Users\arnoudb.WRI>test.wls
Running in test.wls

Then using wolframscript.exe:

C:\Users\arnoudb.WRI>wolframscript
Wolfram Language 11.3.0 Engine for Microsoft Windows (64-bit)
Copyright 1988-2018 Wolfram Research, Inc.

In[1]:= Get["test.wls"]
Running in wolframscript.exe

Then using wolfram.exe:

C:\Users\arnoudb.WRI>"C:\Program Files\Wolfram Research\Mathematica\11.3\wolfram.exe"
Mathematica 11.3.0 Kernel for Microsoft Windows (64-bit)
Copyright 1988-2018 Wolfram Research, Inc.

In[1]:= Get["test.wls"]
Running in wolfram.exe

And finally from a notebook interface:

Get["C:\\Users\\arnoudb.WRI\\test.wls"]

Running in notebook interface

Probably needs some work to get this more solid.

| improve this answer | |
$\endgroup$
  • $\begingroup$ These differentiate between the different environments that run Mathematica code, but not between the "main" file and imported modules, as the Python code does. Running wolframscript -file test.wls will yield the same result as wolframscript -run "Get[\"test.wls\"]". It may be that what I'm asking for isn't possible in Mathematica. $\endgroup$ – Theelepel Oct 6 '18 at 18:18
2
$\begingroup$

The way that works is that when Python runs a source file as the main program, it first sets the variable __name__ to "__main__" (see this answer). As far as I know, Mathematica does no such thing for you, so unless you want to require every source file to include code to replicate that behavior, the closest I can think of is to have the script check if it is being evaluated as part of a Get or Needs expression. Something like:

If[
    MatchQ[Stack[], {___, Get|Needs, If, MatchQ}],
    Print["this will evaluate if being imported by Get or Needs"],
    Print["this will evaluate otherwise"]
]

That being said, I wouldn't really recommend writing code like this and would rethink if this behavior is really necessary.

| improve this answer | |
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.