It does not work either. I think that the cause of this problem is that topDir is a reference object of a pointer to a TDirectory. If it is a reference to a TDirectory, subDir in the following example,
are you sure? What is the output of this session for you:[code]>>> from ROOT import *
topDir = gDirectory.GetDirectory( gDirectory.GetPath() )
print topDir, gDirectory
<ROOT.TROOT object (“PyROOT”) at 0xb7a38f80> <ROOT.TDirectory* object (“PyROOT”) at 0xb7a38178>
f = TFile( ‘test.root’, ‘RECREATE’ )
print topDir, gDirectory
<ROOT.TROOT object (“PyROOT”) at 0xb7a38f80> <ROOT.TDirectory* object (“test.root”) at 0xb7a38178>[/code]
which shows that although gDirectory moves, topDir no longer does?
The underlying to gDirectory is a TDirectory**, the underlying to the result of GetDirectory() is a TDirectory*, so I’m not quite sure how it can’t work.
I tried again. It is depended on where the file is opened. If I start ROOT, open file there and then run "TPython::Prompt()", both topDir and gDirectory are TDirectory* object in python regardless of [b]topDir=gDirectory[/b] or [b]topDir=gDirectory.GetDirectory(gDirectory.GetPath())[/b].
If I start python, topDir would be a TDirectory object for [b]topDir=gDirectory.GetDirectory(gDirectory.GetPath())[/b].
yes, of course: gDirectory always points to the current directory, so after opening a file, the current directory is that file (gDirectory will still be TDirectory** in python, though). If you want to save the top directory from gDirectory, you’d have to do that before opening the file, and the GetDirectory() code snippet does just that. Also, if you start out in root, you could simply do:[code]root [0] topDir = gDirectory;
root [1] f = new TFile( “test.root”, “RECREATE” );
root [2] TPython::Prompt()
print ROOT.gDirectory, ROOT.topDir
<ROOT.TDirectory* object (“test.root”) at 0xb7ec4178> <ROOT.TDirectory* object (“Rint”) at 0x80a56e0>[/code]
so now, gDirectory has moved, but its by-value copy (the semantics of that statement are different in C++ than they are in python) topDir from before opening the file has not. Both topDir and gDirectory are TDirectory** here (in python; C++ types are, of course, still TDirectory*), meaning that if the actual pointer changes on the CINT side, the python side changes with it (compare that with GetDirectory()). E.g., to continue the above session:[code]>>> ^D
root [3] topDir = 0;
root [4] TPython::Prompt()
ROOT.topDir.GetName()
Traceback (most recent call last):
File “/home/wlav/rootdev/root/lib/”, line 1, in
It seems I did not make it clear. In order to make multiple same-level sub-directories, I need the original content of topDir (not top directory: gROOT) in the following example:
[code]root [0] f = new TFile( “test.root”, “RECREATE” );
root [1] TPython::Prompt()
ok, I get it … what is going on is the following: PyROOT keeps track of C++ objects, in case the C++ side decides to delete any of them, so that it can nullify them on the python side (and prevent a crash). These tracked objects are recycled where possible, so the GetDirectory() after the file is returning the recycled gDirectory (which was seen before b/c of the GetPath() call). One option is to delete gDirectory prior to GetDirectory(), and to call GetDirectory() on gROOT instead of gDirectory:[code]>>> cwd = gDirectory.GetPath()
del gDirectory
topDir = gROOT.GetDirectory( cwd )[/code]
but that is rather brittle, as your code may not be the only one having a reference to gDirectory.
The best alternative that I can come up with is:[code]root [0] f = new TFile( “test.root”, “RECREATE” );
root [1] TPython::Prompt()
Sorry about the headache, but making gDirectory behave the way it does (i.e. as TDirectory**) seemed to be the most natural at the time. How about this one:prevDir = gDirectory.GetDirectory('')
Cheers,
Wim
f gDirectory: <ROOT.TDirectory* object ("Hello") at 0xb79e3698>
f.Closed() gDirectory: <ROOT.TDirectory* object ("PyROOT") at 0xb79e3698>
f1 gDirectory: <ROOT.TDirectory* object ("Hello1") at 0xb79e3698>
Which version are you running? Thanks.
Just tried 5.18 myself, and that version does have the problem. What appears to happen, is that the TDirectoryFile that results from mkdir() goes away and signals that, making gDirectory being set to None. Not sure whether that is appropriate, but it doesn’t happen in HEAD. In both cases is the TDirectoryFile properly deleted (and, at that point, signalled).