Dramatically reduce size of frozen/compiled code by pruning/masking unnecessary imports/code

This commit is contained in:
rdb 2016-02-12 22:20:27 +01:00
parent 591ce04ab1
commit 0d03207d1b
14 changed files with 767 additions and 1007 deletions

View File

@ -41,7 +41,9 @@ only when debugging (i.e. when it won't be checked-in) or where it helps
you resist using assert for error handling.
"""
wantVerifyPdb = 0 # Set to true to load pdb on failure.
from panda3d.core import ConfigVariableBool
wantVerifyPdb = ConfigVariableBool('want-verify-pdb', False) # Set to true to load pdb on failure.
def verify(assertion):

View File

@ -12,7 +12,6 @@ from OnscreenImage import *
from direct.directtools.DirectUtil import ROUND_TO
from direct.showbase import DirectObject
from direct.task import Task
from direct.showbase.PythonUtil import recordCreationStackStr
import types
guiObjectCollector = PStatCollector("Client::GuiObjects")
@ -651,13 +650,6 @@ def toggleGuiGridSnap():
def setGuiGridSpacing(spacing):
DirectGuiWidget.gridSpacing = spacing
# this should trigger off of __dev__, but it's not available at this point.
# __debug__ works because the production client is not __debug__ and the
# production AI doesn't create any GUI.
if get_config_showbase().GetBool('record-gui-creation-stack', __debug__):
# this will help track down the code that created DirectGui objects
# call obj.printCreationStackTrace() to figure out what code created it
DirectGuiBase = recordCreationStackStr(DirectGuiBase)
class DirectGuiWidget(DirectGuiBase, NodePath):
# Toggle if you wish widget's to snap to grid when draggin

View File

@ -72,13 +72,6 @@ class ProjectileInterval(Interval):
self.projectileIntervalNum)
ProjectileInterval.projectileIntervalNum += 1
"""
# attempt to add info about the caller
file, line, func = PythonUtil.callerInfo()
if file is not None:
name += '-%s:%s:%s' % (file, line, func)
"""
args = (startPos, endPos, duration, startVel, endZ,
wayPoint, timeToWayPoint, gravityMult)
self.implicitStartPos = 0

View File

@ -1,4 +1,5 @@
from panda3d.direct import get_config_showbase
__all__ = ["install"]
from direct.directnotify.DirectNotifyGlobal import directNotify
from direct.showbase.PythonUtil import fastRepr
import sys
@ -6,7 +7,6 @@ import types
import traceback
notify = directNotify.newCategory("ExceptionVarDump")
config = get_config_showbase()
reentry = 0
@ -187,7 +187,7 @@ def install(log, upload):
wantStackDumpLog = log
wantStackDumpUpload = upload
dumpOnExceptionInit = config.GetBool('variable-dump-on-exception-init', 0)
dumpOnExceptionInit = ConfigVariableBool('variable-dump-on-exception-init', False)
if dumpOnExceptionInit:
# this mode doesn't completely work because exception objects
# thrown by the interpreter don't get created until the

View File

@ -281,7 +281,7 @@ class GarbageReport(Job):
if self._args.findCycles:
s = ['===== GarbageReport: \'%s\' (%s %s) =====' % (
self._args.name, self.numCycles,
choice(self.numCycles == 1, 'cycle', 'cycles'))]
('cycle' if self.numCycles == 1 else 'cycles'))]
else:
s = ['===== GarbageReport: \'%s\' =====' % (
self._args.name)]
@ -499,7 +499,7 @@ class GarbageReport(Job):
rootId = index
# check if the root object is one of the garbage instances (has __del__)
objId = id(self.garbage[rootId])
numDelInstances = choice(objId in self.garbageInstanceIds, 1, 0)
numDelInstances = int(objId in self.garbageInstanceIds)
stateStack.push(([rootId], rootId, numDelInstances, 0))
while True:
yield None
@ -535,7 +535,7 @@ class GarbageReport(Job):
elif refId is not None:
# check if this object is one of the garbage instances (has __del__)
objId = id(self.garbage[refId])
numDelInstances += choice(objId in self.garbageInstanceIds, 1, 0)
numDelInstances += int(objId in self.garbageInstanceIds)
# this refId does not complete a cycle. Mark down
# where we are in this list of referents, then
# start looking through the referents of the new refId

View File

@ -5,7 +5,6 @@ __all__ = ['Diff', 'ObjectPool']
from direct.directnotify.DirectNotifyGlobal import directNotify
from direct.showbase.PythonUtil import invertDictLossless, makeList, safeRepr
from direct.showbase.PythonUtil import getNumberedTypedString, getNumberedTypedSortedString
from direct.showbase.PythonUtil import getNumberedTypedSortedStringWithReferrersGen
import gc
class Diff:
@ -97,7 +96,7 @@ class ObjectPool:
s += '\n%s\t%s' % (count, typ)
return s
def printObjsByType(self, printReferrers=False):
def printObjsByType(self):
print 'Object Pool: Objects By Type'
print '\n============================'
counts = list(set(self._count2types.keys()))
@ -109,11 +108,7 @@ class ObjectPool:
types = makeList(self._count2types[count])
for typ in types:
print 'TYPE: %s, %s objects' % (repr(typ), len(self._type2objs[typ]))
if printReferrers:
for line in getNumberedTypedSortedStringWithReferrersGen(self._type2objs[typ]):
print line
else:
print getNumberedTypedSortedString(self._type2objs[typ])
print getNumberedTypedSortedString(self._type2objs[typ])
def containerLenStr(self):
s = 'Object Pool: Container Lengths'

File diff suppressed because it is too large Load Diff

View File

@ -26,24 +26,22 @@ from BulletinBoardGlobal import bulletinBoard
from direct.task.TaskManagerGlobal import taskMgr
from JobManagerGlobal import jobMgr
from EventManagerGlobal import eventMgr
from PythonUtil import *
from direct.showbase import PythonUtil
#from direct.interval.IntervalManager import ivalMgr
#from PythonUtil import *
from direct.interval import IntervalManager
from direct.showbase.BufferViewer import BufferViewer
from direct.task import Task
from direct.directutil import Verify
from direct.showbase import GarbageReport
import sys
import Loader
import time
import atexit
import importlib
from direct.showbase import ExceptionVarDump
import DirectObject
import SfxPlayer
if __debug__:
from direct.showbase import GarbageReport
from direct.directutil import DeltaProfiler
import OnScreenDebug
import OnScreenDebug
import AppRunnerGlobal
def legacyRun():
@ -73,7 +71,8 @@ class ShowBase(DirectObject.DirectObject):
if logStackDump or uploadStackDump:
ExceptionVarDump.install(logStackDump, uploadStackDump)
self.__autoGarbageLogging = self.__dev__ and self.config.GetBool('auto-garbage-logging', False)
if __debug__:
self.__autoGarbageLogging = self.__dev__ and self.config.GetBool('auto-garbage-logging', False)
## The directory containing the main Python file of this application.
self.mainDir = ExecutionEnvironment.getEnvironmentVariable("MAIN_DIR")
@ -88,9 +87,6 @@ class ShowBase(DirectObject.DirectObject):
#debug running multiplier
self.debugRunningMultiplier = 4
# Setup wantVerifyPdb as soon as reasonable:
Verify.wantVerifyPdb = self.config.GetBool('want-verify-pdb', 0)
# [gjeon] to disable sticky keys
if self.config.GetBool('disable-sticky-keys', 0):
storeAccessibilityShortcutKeys()
@ -373,8 +369,8 @@ class ShowBase(DirectObject.DirectObject):
builtins.wantUberdog = self.config.GetBool('want-uberdog', 1)
if __debug__:
builtins.deltaProfiler = DeltaProfiler.DeltaProfiler("ShowBase")
self.onScreenDebug = OnScreenDebug.OnScreenDebug()
builtins.onScreenDebug = self.onScreenDebug
self.onScreenDebug = OnScreenDebug.OnScreenDebug()
builtins.onScreenDebug = self.onScreenDebug
if self.wantRender2dp:
builtins.render2dp = self.render2dp
@ -388,10 +384,6 @@ class ShowBase(DirectObject.DirectObject):
self.createBaseAudioManagers()
# set up recording of Functor creation stacks in __dev__
if self.__dev__ and self.config.GetBool('record-functor-creation-stacks', False):
PythonUtil.recordFunctorCreationStacks()
if self.__dev__ or self.config.GetBool('want-e3-hacks', False):
if self.config.GetBool('track-gui-items', True):
# dict of guiId to gui item, for tracking down leaks
@ -465,7 +457,8 @@ class ShowBase(DirectObject.DirectObject):
some Panda config settings. """
try:
import profile, pstats
profile = importlib.import_module('profile')
pstats = importlib.import_module('pstats')
except ImportError:
return
@ -1647,23 +1640,26 @@ class ShowBase(DirectObject.DirectObject):
def addAngularIntegrator(self):
if not self.physicsMgrAngular:
from panda3d.physics import AngularEulerIntegrator
physics = importlib.import_module('panda3d.physics')
self.physicsMgrAngular = 1
integrator = AngularEulerIntegrator()
integrator = physics.AngularEulerIntegrator()
self.physicsMgr.attachAngularIntegrator(integrator)
def enableParticles(self):
if not self.particleMgrEnabled:
# Use importlib to prevent this import from being picked up
# by modulefinder when packaging an application.
if not self.particleMgr:
from direct.particles.ParticleManagerGlobal import particleMgr
self.particleMgr = particleMgr
PMG = importlib.import_module('direct.particles.ParticleManagerGlobal')
self.particleMgr = PMG.particleMgr
self.particleMgr.setFrameStepping(1)
if not self.physicsMgr:
from PhysicsManagerGlobal import physicsMgr
from panda3d.physics import LinearEulerIntegrator
self.physicsMgr = physicsMgr
integrator = LinearEulerIntegrator()
PMG = importlib.import_module('direct.showbase.PhysicsManagerGlobal')
physics = importlib.import_module('panda3d.physics')
self.physicsMgr = PMG.physicsMgr
integrator = physics.LinearEulerIntegrator()
self.physicsMgr.attachLinearIntegrator(integrator)
self.particleMgrEnabled = 1
@ -1886,9 +1882,10 @@ class ShowBase(DirectObject.DirectObject):
return Task.cont
def __igLoop(self, state):
# We render the watch variables for the onScreenDebug as soon
# as we reasonably can before the renderFrame().
self.onScreenDebug.render()
if __debug__:
# We render the watch variables for the onScreenDebug as soon
# as we reasonably can before the renderFrame().
self.onScreenDebug.render()
if self.recorder:
self.recorder.recordFrame()
@ -1900,9 +1897,10 @@ class ShowBase(DirectObject.DirectObject):
if self.multiClientSleep:
time.sleep(0)
# We clear the text buffer for the onScreenDebug as soon
# as we reasonably can after the renderFrame().
self.onScreenDebug.clear()
if __debug__:
# We clear the text buffer for the onScreenDebug as soon
# as we reasonably can after the renderFrame().
self.onScreenDebug.clear()
if self.recorder:
self.recorder.playFrame()
@ -1925,9 +1923,10 @@ class ShowBase(DirectObject.DirectObject):
def __igLoopSync(self, state):
# We render the watch variables for the onScreenDebug as soon
# as we reasonably can before the renderFrame().
self.onScreenDebug.render()
if __debug__:
# We render the watch variables for the onScreenDebug as soon
# as we reasonably can before the renderFrame().
self.onScreenDebug.render()
if self.recorder:
self.recorder.recordFrame()
@ -1941,9 +1940,10 @@ class ShowBase(DirectObject.DirectObject):
if self.multiClientSleep:
time.sleep(0)
# We clear the text buffer for the onScreenDebug as soon
# as we reasonably can after the renderFrame().
self.onScreenDebug.clear()
if __debug__:
# We clear the text buffer for the onScreenDebug as soon
# as we reasonably can after the renderFrame().
self.onScreenDebug.clear()
if self.recorder:
self.recorder.playFrame()
@ -2178,8 +2178,10 @@ class ShowBase(DirectObject.DirectObject):
self.texmem = None
return
from direct.showutil.TexMemWatcher import TexMemWatcher
self.texmem = TexMemWatcher()
# Use importlib to prevent this import from being picked up
# by modulefinder when packaging an application.
TMW = importlib.import_module('direct.showutil.TexMemWatcher')
self.texmem = TMW.TexMemWatcher()
def toggleShowVertices(self):
""" Toggles a mode that visualizes vertex density per screen
@ -2675,16 +2677,18 @@ class ShowBase(DirectObject.DirectObject):
if not properties.getOpen():
# If the user closes the main window, we should exit.
self.notify.info("User closed main window.")
if self.__autoGarbageLogging:
GarbageReport.b_checkForGarbageLeaks()
if __debug__:
if self.__autoGarbageLogging:
GarbageReport.b_checkForGarbageLeaks()
self.userExit()
if properties.getForeground() and not self.mainWinForeground:
self.mainWinForeground = 1
elif not properties.getForeground() and self.mainWinForeground:
self.mainWinForeground = 0
if self.__autoGarbageLogging:
GarbageReport.b_checkForGarbageLeaks()
if __debug__:
if self.__autoGarbageLogging:
GarbageReport.b_checkForGarbageLeaks()
if properties.getMinimized() and not self.mainWinMinimized:
# If the main window is minimized, throw an event to
@ -2814,7 +2818,10 @@ class ShowBase(DirectObject.DirectObject):
init_app_for_gui()
import wx
# Use importlib to prevent this import from being picked up
# by modulefinder when packaging an application.
wx = importlib.import_module('wx')
# Create a new base.wxApp.
self.wxApp = wx.PySimpleApp(redirect = False)
@ -2889,8 +2896,10 @@ class ShowBase(DirectObject.DirectObject):
# Don't do this twice.
return
from Tkinter import tkinter
import Pmw
# Use importlib to prevent this import from being picked up
# by modulefinder when packaging an application.
tkinter = importlib.import_module('Tkinter').tkinter
Pmw = importlib.import_module('Pmw')
# Create a new Tk root.
self.tkRoot = Pmw.initialise()
@ -2953,8 +2962,10 @@ class ShowBase(DirectObject.DirectObject):
self.startWx(fWantWx)
self.wantDirect = fWantDirect
if self.wantDirect:
from direct.directtools.DirectSession import DirectSession
self.direct = DirectSession()
# Use importlib to prevent this import from being picked up
# by modulefinder when packaging an application.
DirectSession = importlib.import_module('direct.directtools.DirectSession')
self.direct = DirectSession.DirectSession()
self.direct.enable()
builtins.direct = self.direct
else:

View File

@ -3,7 +3,7 @@
__all__ = ['Transitions']
from panda3d.core import *
from direct.gui.DirectGui import *
from direct.gui.DirectGui import DirectFrame
from direct.gui import DirectGuiGlobals as DGG
from direct.interval.LerpInterval import LerpColorScaleInterval, LerpColorInterval, LerpScaleInterval, LerpPosInterval
from direct.interval.MetaInterval import Sequence, Parallel

View File

@ -30,8 +30,8 @@ isDebugBuild = (python.lower().endswith('_d'))
# These are modules that Python always tries to import up-front. They
# must be frozen in any main.exe.
startupModules = [
'site', 'sitecustomize', 'os', 'encodings.cp1252',
'encodings.latin_1', 'encodings.utf_8', 'io', 'org',
'os', 'encodings.cp1252',
'encodings.latin_1', 'encodings.utf_8', 'io',
]
# These are missing modules that we've reported already this session.

View File

@ -70,6 +70,13 @@ class LockType:
def __exit__(self, t, v, tb):
self.release()
# Helper to generate new thread names
_counter = 0
def _newname(template="Thread-%d"):
global _counter
_counter = _counter + 1
return template % _counter
_threads = {}
_nextThreadId = 0
_threadsLock = core.Mutex('thread._threadsLock')

View File

@ -42,6 +42,7 @@ __all__ = [
]
local = _thread._local
_newname = _thread._newname
class ThreadBase:
""" A base class for both Thread and ExternalThread in this
@ -98,8 +99,7 @@ class Thread(ThreadBase):
self.__kwargs = kwargs
if not name:
import threading2
name = threading2._newname()
name = _newname()
current = current_thread()
self.__dict__['daemon'] = current.daemon
@ -404,106 +404,107 @@ def setprofile(func):
def stack_size(size = None):
raise ThreadError
def _test():
if __debug__:
def _test():
from collections import deque
from collections import deque
_sleep = core.Thread.sleep
_sleep = core.Thread.sleep
_VERBOSE = False
_VERBOSE = False
class _Verbose(object):
class _Verbose(object):
def __init__(self, verbose=None):
if verbose is None:
verbose = _VERBOSE
self.__verbose = verbose
def __init__(self, verbose=None):
if verbose is None:
verbose = _VERBOSE
self.__verbose = verbose
def _note(self, format, *args):
if self.__verbose:
format = format % args
format = "%s: %s\n" % (
currentThread().getName(), format)
_sys.stderr.write(format)
def _note(self, format, *args):
if self.__verbose:
format = format % args
format = "%s: %s\n" % (
currentThread().getName(), format)
_sys.stderr.write(format)
class BoundedQueue(_Verbose):
class BoundedQueue(_Verbose):
def __init__(self, limit):
_Verbose.__init__(self)
self.mon = Lock(name = "BoundedQueue.mon")
self.rc = Condition(self.mon)
self.wc = Condition(self.mon)
self.limit = limit
self.queue = deque()
def __init__(self, limit):
_Verbose.__init__(self)
self.mon = Lock(name = "BoundedQueue.mon")
self.rc = Condition(self.mon)
self.wc = Condition(self.mon)
self.limit = limit
self.queue = deque()
def put(self, item):
self.mon.acquire()
while len(self.queue) >= self.limit:
self._note("put(%s): queue full", item)
self.wc.wait()
self.queue.append(item)
self._note("put(%s): appended, length now %d",
item, len(self.queue))
self.rc.notify()
self.mon.release()
def put(self, item):
self.mon.acquire()
while len(self.queue) >= self.limit:
self._note("put(%s): queue full", item)
self.wc.wait()
self.queue.append(item)
self._note("put(%s): appended, length now %d",
item, len(self.queue))
self.rc.notify()
self.mon.release()
def get(self):
self.mon.acquire()
while not self.queue:
self._note("get(): queue empty")
self.rc.wait()
item = self.queue.popleft()
self._note("get(): got %s, %d left", item, len(self.queue))
self.wc.notify()
self.mon.release()
return item
def get(self):
self.mon.acquire()
while not self.queue:
self._note("get(): queue empty")
self.rc.wait()
item = self.queue.popleft()
self._note("get(): got %s, %d left", item, len(self.queue))
self.wc.notify()
self.mon.release()
return item
class ProducerThread(Thread):
class ProducerThread(Thread):
def __init__(self, queue, quota):
Thread.__init__(self, name="Producer")
self.queue = queue
self.quota = quota
def __init__(self, queue, quota):
Thread.__init__(self, name="Producer")
self.queue = queue
self.quota = quota
def run(self):
from random import random
counter = 0
while counter < self.quota:
counter = counter + 1
self.queue.put("%s.%d" % (self.getName(), counter))
_sleep(random() * 0.00001)
def run(self):
from random import random
counter = 0
while counter < self.quota:
counter = counter + 1
self.queue.put("%s.%d" % (self.getName(), counter))
_sleep(random() * 0.00001)
class ConsumerThread(Thread):
class ConsumerThread(Thread):
def __init__(self, queue, count):
Thread.__init__(self, name="Consumer")
self.queue = queue
self.count = count
def __init__(self, queue, count):
Thread.__init__(self, name="Consumer")
self.queue = queue
self.count = count
def run(self):
while self.count > 0:
item = self.queue.get()
print item
self.count = self.count - 1
def run(self):
while self.count > 0:
item = self.queue.get()
print item
self.count = self.count - 1
NP = 3
QL = 4
NI = 5
NP = 3
QL = 4
NI = 5
Q = BoundedQueue(QL)
P = []
for i in range(NP):
t = ProducerThread(Q, NI)
t.setName("Producer-%d" % (i+1))
P.append(t)
C = ConsumerThread(Q, NI*NP)
for t in P:
t.start()
_sleep(0.000001)
C.start()
for t in P:
t.join()
C.join()
Q = BoundedQueue(QL)
P = []
for i in range(NP):
t = ProducerThread(Q, NI)
t.setName("Producer-%d" % (i+1))
P.append(t)
C = ConsumerThread(Q, NI*NP)
for t in P:
t.start()
_sleep(0.000001)
C.start()
for t in P:
t.join()
C.join()
if __name__ == '__main__':
_test()
if __name__ == '__main__':
_test()

View File

@ -16,13 +16,12 @@ implementation. """
import sys as _sys
from direct.stdpy import thread
from direct.stdpy.thread import stack_size, _local as local
from direct.stdpy.thread import stack_size, _newname, _local as local
from panda3d import core
_sleep = core.Thread.sleep
from time import time as _time
from traceback import format_exc as _format_exc
from collections import deque
# Rename some stuff so "from threading import *" is safe
__all__ = ['activeCount', 'Condition', 'currentThread', 'enumerate', 'Event',
@ -377,13 +376,6 @@ class _Event(_Verbose):
finally:
self.__cond.release()
# Helper to generate new thread names
_counter = 0
def _newname(template="Thread-%d"):
global _counter
_counter = _counter + 1
return template % _counter
# Active thread administration
_active_limbo_lock = _allocate_lock()
_active = {} # maps thread id to Thread object
@ -741,88 +733,89 @@ _shutdown = _MainThread()._exitfunc
# Self-test code
if __debug__:
def _test():
from collections import deque
def _test():
class BoundedQueue(_Verbose):
class BoundedQueue(_Verbose):
def __init__(self, limit):
_Verbose.__init__(self)
self.mon = RLock()
self.rc = Condition(self.mon)
self.wc = Condition(self.mon)
self.limit = limit
self.queue = deque()
def __init__(self, limit):
_Verbose.__init__(self)
self.mon = RLock()
self.rc = Condition(self.mon)
self.wc = Condition(self.mon)
self.limit = limit
self.queue = deque()
def put(self, item):
self.mon.acquire()
while len(self.queue) >= self.limit:
self._note("put(%s): queue full", item)
self.wc.wait()
self.queue.append(item)
self._note("put(%s): appended, length now %d",
item, len(self.queue))
self.rc.notify()
self.mon.release()
def put(self, item):
self.mon.acquire()
while len(self.queue) >= self.limit:
self._note("put(%s): queue full", item)
self.wc.wait()
self.queue.append(item)
self._note("put(%s): appended, length now %d",
item, len(self.queue))
self.rc.notify()
self.mon.release()
def get(self):
self.mon.acquire()
while not self.queue:
self._note("get(): queue empty")
self.rc.wait()
item = self.queue.popleft()
self._note("get(): got %s, %d left", item, len(self.queue))
self.wc.notify()
self.mon.release()
return item
def get(self):
self.mon.acquire()
while not self.queue:
self._note("get(): queue empty")
self.rc.wait()
item = self.queue.popleft()
self._note("get(): got %s, %d left", item, len(self.queue))
self.wc.notify()
self.mon.release()
return item
class ProducerThread(Thread):
class ProducerThread(Thread):
def __init__(self, queue, quota):
Thread.__init__(self, name="Producer")
self.queue = queue
self.quota = quota
def __init__(self, queue, quota):
Thread.__init__(self, name="Producer")
self.queue = queue
self.quota = quota
def run(self):
from random import random
counter = 0
while counter < self.quota:
counter = counter + 1
self.queue.put("%s.%d" % (self.getName(), counter))
_sleep(random() * 0.00001)
def run(self):
from random import random
counter = 0
while counter < self.quota:
counter = counter + 1
self.queue.put("%s.%d" % (self.getName(), counter))
_sleep(random() * 0.00001)
class ConsumerThread(Thread):
class ConsumerThread(Thread):
def __init__(self, queue, count):
Thread.__init__(self, name="Consumer")
self.queue = queue
self.count = count
def __init__(self, queue, count):
Thread.__init__(self, name="Consumer")
self.queue = queue
self.count = count
def run(self):
while self.count > 0:
item = self.queue.get()
print item
self.count = self.count - 1
def run(self):
while self.count > 0:
item = self.queue.get()
print item
self.count = self.count - 1
NP = 3
QL = 4
NI = 5
NP = 3
QL = 4
NI = 5
Q = BoundedQueue(QL)
P = []
for i in range(NP):
t = ProducerThread(Q, NI)
t.setName("Producer-%d" % (i+1))
P.append(t)
C = ConsumerThread(Q, NI*NP)
for t in P:
t.start()
_sleep(0.000001)
C.start()
for t in P:
t.join()
C.join()
Q = BoundedQueue(QL)
P = []
for i in range(NP):
t = ProducerThread(Q, NI)
t.setName("Producer-%d" % (i+1))
P.append(t)
C = ConsumerThread(Q, NI*NP)
for t in P:
t.start()
_sleep(0.000001)
C.start()
for t in P:
t.join()
C.join()
if __name__ == '__main__':
_test()
if __name__ == '__main__':
_test()

View File

@ -12,6 +12,7 @@ from direct.showbase.PythonUtil import *
from direct.showbase.MessengerGlobal import messenger
import types
import random
import importlib
try:
import signal
@ -591,7 +592,6 @@ class TaskManager:
def popupControls(self):
# Don't use a regular import, to prevent ModuleFinder from picking
# it up as a dependency when building a .p3d package.
import importlib
TaskManagerPanel = importlib.import_module('direct.tkpanels.TaskManagerPanel')
return TaskManagerPanel.TaskManagerPanel(self)
@ -602,8 +602,8 @@ class TaskManager:
# Defer this import until we need it: some Python
# distributions don't provide the profile and pstats modules.
from direct.showbase.ProfileSession import ProfileSession
return ProfileSession(name)
PS = importlib.import_module('direct.showbase.ProfileSession')
return PS.ProfileSession(name)
def profileFrames(self, num=None, session=None, callback=None):
if num is None:
@ -629,8 +629,8 @@ class TaskManager:
self._profileFrames.set(profileFrames)
if (not self._frameProfiler) and profileFrames:
# import here due to import dependencies
from direct.task.FrameProfiler import FrameProfiler
self._frameProfiler = FrameProfiler()
FP = importlib.import_module('direct.task.FrameProfiler')
self._frameProfiler = FP.FrameProfiler()
def getProfileTasks(self):
return self._profileTasks.get()
@ -642,8 +642,8 @@ class TaskManager:
self._profileTasks.set(profileTasks)
if (not self._taskProfiler) and profileTasks:
# import here due to import dependencies
from direct.task.TaskProfiler import TaskProfiler
self._taskProfiler = TaskProfiler()
TP = importlib.import_module('direct.task.TaskProfiler')
self._taskProfiler = TP.TaskProfiler()
def logTaskProfiles(self, name=None):
if self._taskProfiler:
@ -689,9 +689,9 @@ class TaskManager:
# Defer this import until we need it: some Python
# distributions don't provide the profile and pstats modules.
from direct.showbase.ProfileSession import ProfileSession
profileSession = ProfileSession('profiled-task-%s' % task.getName(),
Functor(profileInfo.taskFunc, *profileInfo.taskArgs))
PS = importlib.import_module('direct.showbase.ProfileSession')
profileSession = PS.ProfileSession('profiled-task-%s' % task.getName(),
Functor(profileInfo.taskFunc, *profileInfo.taskArgs))
ret = profileSession.run()
# set these values *after* profiling in case we're profiling the TaskProfiler