Page MenuHome

Python scripts executed from commandline don't have __main__ module's dict as their globals on Windows
Closed, ResolvedPublic

Description

System Information
Windows 7 & W8100

Blender Version
Broken: 2.78c

Short description of error
When a python file is executed with --python it's namespace is different from __main__ module's namespace. This, for example, prevents unittest.main() from collecting tests(unittest.main collects tests by importing __main__ module). So any tests scripts(including Blender's python tests) relying on unittest.main behavior are now passing, having collected 0 Tests.

Exact steps for others to reproduce the error
Here's the test file, that shows that namespace is not __main__'s -


running it (blender.exe --background --python test.py) gives this:

['__builtins__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'f', 'ns']

----------------------------------------------------------------------
Ran 0 tests in 0.000s

Cause and fix

On Windows globals() is copied for some reason before being passed to exec. Removing copy() fixes the problem:

---
 source/blender/python/intern/bpy_interface.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/source/blender/python/intern/bpy_interface.c b/source/blender/python/intern/bpy_interface.c
index 55e477b0214..9cfa98b12b1 100644
--- a/source/blender/python/intern/bpy_interface.c
+++ b/source/blender/python/intern/bpy_interface.c
@@ -483,7 +483,7 @@ static bool python_script_exec(
             * So now we load the script file data to a buffer */
            {
                const char *pystring =
-                       "ns = globals().copy()\n"
+                       "ns = globals()\n"
                        "with open(__file__, 'rb') as f: exec(compile(f.read(), __file__, 'exec'), ns)";
 
                fclose(fp);
-- 

Revisions and Commits

Event Timeline

Sergey Sharybin (sergey) lowered the priority of this task from 90 to Normal.

@Campbell Barton (campbellbarton), afraid you are the only one to knwo why globals are being copied. Mind having a look here? :)

The problem was caused by unittest module inspecting sys.modules[__name__] - executing with globals().copy() for globals meant that classes defined in the code weren't added to sys.modules[__name__] for unittest to discover.

Committed this change with a minor kludge to avoid f variable being declared for every script being executed.