-2

I need to have a couple of functions in Python (either variation) to find and print the name of the file they are stored or called from. For example, consider the following functions are stored in at this address: /my/py/func.py:

def this_file():
# print the address of this file
print('this function is stored at %s' % this_file_address)

and

def that_file():
# print the address of the file that is calling this function
print('this function is called form a file at %s' % that_file_address)

And I have a piece of code stored in /my/py/calls.py:

from func import *
this_file()
that_file()

Now, I want the followings to be printed by the above functions:

/my/py/func.py 
/my/py/calls.py

How can I write these functions?


Edit #1 It seems calling that_file() from Jupyter notebooks should be handled differently.

HoldOffHunger
  • 18,769
  • 10
  • 104
  • 133
Borhan Kazimipour
  • 405
  • 1
  • 6
  • 13

2 Answers2

0
import os                                                                                                                                                           
import sys
def this_file():
         print(os.path.realpath(__file__))

def that_file():
        print(os.getcwd() + "/" + sys.argv[0])

I think this is what you're looking for.

quantik
  • 776
  • 12
  • 26
  • Thank for the quick and helpful answer. You solution works perfectly fine in ordinary Python script, but not in Jupyter notebook. For example if I call them from a .ipynb file, I get the following: `/home/jovyan/work/func.py /home/jovyan/work//opt/conda/lib/python3.6/site-packages/ipykernel_launcher.py` It seems argv[0] always point to `/opt/conda/lib/python3.6/site-packages/ipykernel_launcher.py` – Borhan Kazimipour Mar 05 '18 at 02:06
0

Thanks to @quantik and @Iguananaut (see this), I could find a more general solution that works for calling Python functions from .py and .ipynb files:

func.py

Content:
import os.path                                                                                                                               
import sys
import urllib.request
import json

def this_file():
    # prints the address of this file
    print(__file__)
    return __file__


def that_file():
    # prints the address of the file that is calling this function
    if sys.argv[0][-21:]=='ipykernel_launcher.py':
        print('Are you calling me from a Jupyter Notebook? Try "that_notebook()" instead.')
        return False
    else:
        print(os.getcwd() + "/" + sys.argv[0])
        return os.getcwd() + "/" + sys.argv[0]


def that_notebook(base_url='http://127.0.0.1:8888'):
    # prints the address of the notebook that is calling this function
    ## read more about Jupyter APIL: https://github.com/jupyter/jupyter/wiki/Jupyter-Notebook-Server-API

    # See if the url is correct
    try:
        sessions = json.load(urllib.request.urlopen(base_url+'/api/sessions'))
    except:
        print('Oops! %s is an invalid URL.' % (base_url+'/api/sessions'))
        return False

    # See if there is any active session
    if len(sessions) == 0:
        print('No active session found!')
        print('Are you calling me from a Python file? Try "that_file()" instead.')
        return False

    # In case of multiple active sessions, only print the most recently 
    latest=max([s['kernel']['last_activity'] for s in sessions])
    for s in sessions:    
        if s['kernel']['last_activity']==latest:
            print(s['path'])
            return(s['path'])

calls.py

Contents:
from func import *
this_file()
that_file()
that_notebook()
Outputs:

python calls.py

/home/jovyan/work/calls.py
No active session found!
Are you calling me from a Python file? Try "that_file()" instead.
jovyan@c5cd7b908543:~/work$

calls.ipynb

Contents:
from func import *
this_file()
that_file()
that_notebook()
Outputs:

calls.ipynb

/home/jovyan/work/func.py
Are you calling me from a Jupyter Notebook? Try "that_notebook()" instead.
work/calls.ipynb
Borhan Kazimipour
  • 405
  • 1
  • 6
  • 13