0

I'm writing a general purpose printing class:

from __future__ import division
import os.path

class pprint:
    def __init__(self, name, path=None):
        self.name = name
        if path == None:
            #Where we define the path
            ???
        self.path = path
        self.complete_name = os.path.join(path, name)
        self.f = open(complete_name, "w")

    def __call__(text):
        self.f.write(text + "\n")
        print text

The constructor takes the name of the file to write to and an optional argument containing that file's path. If the user does not specify the path, I want it to write to the directory of the calling program. The only thing I don't know how to do is the latter conditional: if no path is specified, assume that the path is that of the calling function.
How do I find this out? Essentially, I want to look on the python function stack, find out what function is calling pprint, find the path of that file, and then set path to be the path of that file. I, however, know NOTHING about how the python function stack works. How do I do this?
Thanks!

EDIT: I don't want the path of the __main__ file. If I have a.py call b.py and b.py call pprint.py, I don't want the path of a.py. The paths of a.py and b.py might be quite different.

EDIT 2: I'm using Python 2.7.6. I'm on Ubuntu 14.04, if that's relevant. I use the thing that came built-in, with some other stuff like numpy, scipy, pylab, etc. appended. I have no IDE. I use vim and Terminal. EDIT on EDIT: Whoops! As one post commented, Ubuntu built-in python IS CPython. My bad. So, I am using CPython...

QuantumFool
  • 609
  • 3
  • 10
  • 29
  • Having read the question, it seems that you really just want to get the main file path. As such, I'm voting to close as a duplicate of [How to get filename of the \_\_main\_\_ module in Python?](http://stackoverflow.com/questions/606561/how-to-get-filename-of-the-main-module-in-python). Please clarify your question if this is not what you intend. – jpmc26 Feb 10 '15 at 00:19
  • I believe that you'll need `inspect.stack` – mgilson Feb 10 '15 at 00:23
  • @jpmc26 Not really. If I have a.py call b.py and b.py call pprint.py, I want the path to b.py, not a.py. They could be quite different. – QuantumFool Feb 10 '15 at 00:25
  • @QuantumFool So... if you install your modules as an egg, and `main.py` calls `b.py` which lives in `site-packages`, and `b.py` calls this module, you want the file to output in `site-packages`? This seems rather an ill-advised default. – jpmc26 Feb 10 '15 at 00:26
  • Not knowing what your situation is exactly, I can't really say what the best thing to do would be, but I can think of two pretty common situations. If it's command line, the normal default location for output files is current directory. If it's a web app or service, a configured location would be appropriate. In either case, "next to the module calling this one" doesn't tend to be a sensible default. It's fraught with assumptions about how the modules are arrange, where they're installed, and how the code is organized. It may even make sense to simply not have a default. Regardless, good luck. – jpmc26 Feb 10 '15 at 00:34
  • If you're not using CPython, it would be helpful to indicate which implementation you're using. PyPy? Jython? Telling us which ones you're *not* using doesn't give us much to figure out what your particular interpreter might do differently. – jpmc26 Feb 10 '15 at 00:36
  • 1
    Are you aware that CPython *is* the default Python interpreter on Ubuntu? If you're not specifiically using PyPy, Jython, IronPython, or any other variant, then you *are* using CPython. It's what most people mean when they say "I'm using Python". If you just type "python" or "python3" in your terminal to get to your interpreter or execute scripts, then you're using CPython. – skrrgwasme Feb 10 '15 at 00:37
  • @skrrgwasme Whoops! I figured, since I didn't change anything to my Ubuntu, I wouldn't be using some fancy extra thing. I changed the post to indicate that. – QuantumFool Feb 10 '15 at 00:40
  • 1
    No worries. I know it's a bit confusing for new Python users. You should give the [Implementations section of Python's Wikipedia page](http://en.wikipedia.org/wiki/Python_%28programming_language%29#Implementations) a read. It's short and does a pretty good job of describing popular implementations. – skrrgwasme Feb 10 '15 at 00:44

1 Answers1

1

You can use inspect.getouterframes to get the caller's frame, plus the filename and line number etc.

from __future__ import division

import inspect
import os.path

class pprint(object):
    def __init__(self, name, path=None):
        self.name = name
        if path == None:
           path = inspect.getouterframes(inspect.currentframe())[1][3] 

        self.path = path
        self.complete_name = os.path.join(path, name)
        self.f = open(complete_name, "w")
        ...

I assumed you are using Python 2.7 and CPython or Jython.

Ozgur Vatansever
  • 49,246
  • 17
  • 84
  • 119