160

When I run this code in python 2.7, I get this error:

Traceback (most recent call last):
File "C:\Python26\Lib\site-packages\pyutilib.subprocess-3.5.4\setup.py", line 30, in <module>
    long_description = read('README.txt'),
  File "C:\Python26\Lib\site-packages\pyutilib.subprocess-3.5.4\setup.py", line 19, in read
    return open(os.path.join(os.path.dirname(__file__), *rnames)).read()
NameError: global name '__file__' is not defined

code is:

import os
from setuptools import setup


def read(*rnames):
    return open(os.path.join(os.path.dirname(__file__), *rnames)).read()


setup(name="pyutilib.subprocess",
    version='3.5.4',
    maintainer='William E. Hart',
    maintainer_email='wehart@sandia.gov',
    url = 'https://software.sandia.gov/svn/public/pyutilib/pyutilib.subprocess',
    license = 'BSD',
    platforms = ["any"],
    description = 'PyUtilib utilites for managing subprocesses.',
    long_description = read('README.txt'),
    classifiers = [
        'Development Status :: 4 - Beta',
        'Intended Audience :: End Users/Desktop',
        'License :: OSI Approved :: BSD License',
        'Natural Language :: English',
        'Operating System :: Microsoft :: Windows',
        'Operating System :: Unix',
        'Programming Language :: Python',
        'Programming Language :: Unix Shell',
        'Topic :: Scientific/Engineering :: Mathematics',
        'Topic :: Software Development :: Libraries :: Python Modules'],
      packages=['pyutilib', 'pyutilib.subprocess', 'pyutilib.subprocess.tests'],
      keywords=['utility'],
      namespace_packages=['pyutilib'],
      install_requires=['pyutilib.common', 'pyutilib.services']
      )
smci
  • 32,567
  • 20
  • 113
  • 146
Kaibing Yang
  • 1,603
  • 2
  • 12
  • 5

14 Answers14

183

This error comes when you append this line os.path.join(os.path.dirname(__file__)) in python interactive shell.

Python Shell doesn't detect current file path in __file__ and it's related to your filepath in which you added this line

So you should write this line os.path.join(os.path.dirname(__file__)) in file.py. and then run python file.py, It works because it takes your filepath.

Nilesh
  • 2,407
  • 1
  • 12
  • 20
  • 18
    exactly my experience. but how to get it to work within a shell? – s2t2 May 29 '18 at 15:35
  • 2
    But to run `file.py` from a script, you would put it in the same directory as your script for example. So you need to move to this directory before running `file.py`... So still something better is sought. – ztyh Aug 24 '18 at 17:12
  • So Emacs uses an interactive shell when you C-c C-p? python-shell. Is there a way to use this shell as if it were a terminal running the file? There are 3 options for running the shell : CMD DEDICATED SHOW Would one of them do this? – sinekonata Jul 02 '20 at 00:43
  • So this is not an answer for setuptools because if you distribute your package and use build with twine as pypi.org directs then none of this answer is helpful because the `setup.py` will be copied and executed in a virtualenv and no longer be able to relatively find the orphan files – Stof Nov 03 '21 at 23:41
39

I had the same problem with PyInstaller and Py2exe so I came across the resolution on the FAQ from cx-freeze.

When using your script from the console or as an application, the functions hereunder will deliver you the "execution path", not the "actual file path":

print(os.getcwd())
print(sys.argv[0])
print(os.path.dirname(os.path.realpath('__file__')))

Source:
http://cx-freeze.readthedocs.org/en/latest/faq.html

Your old line (initial question):

def read(*rnames):
return open(os.path.join(os.path.dirname(__file__), *rnames)).read()

Substitute your line of code with the following snippet.

def find_data_file(filename):
    if getattr(sys, 'frozen', False):
        # The application is frozen
        datadir = os.path.dirname(sys.executable)
    else:
        # The application is not frozen
        # Change this bit to match where you store your data files:
        datadir = os.path.dirname(__file__)

    return os.path.join(datadir, filename)

With the above code you could add your application to the path of your os, you could execute it anywhere without the problem that your app is unable to find it's data/configuration files.

Tested with python:

  • 3.3.4
  • 2.7.13
Kwuite
  • 576
  • 5
  • 6
  • 2
    `os.path.realpath('__file__')` doesn't work because it's between quotes. the rest of the answer is good – Jean-François Fabre Feb 17 '21 at 14:08
  • for me `os.path.realpath('__file__')` or `os.path.abspath('__file__')` do work only if `_file_` is between quotes. @Jean-FrançoisFabre – TeYaP Aug 09 '22 at 06:49
  • 1
    what happens is that `realpath` doesn't check if `"__file__"` exists, it just returns current dir + "/__file__" without checking anything, so this is as good as `os.getcwd()` when `__file__` isn't defined. The real solution is to use `sys.executable` on the main python file as the rest of the answer explains – Jean-François Fabre Aug 09 '22 at 09:06
27

I've run into cases where __file__ doesn't work as expected. But the following hasn't failed me so far:

import inspect
src_file_path = inspect.getfile(lambda: None)

This is the closest thing to a Python analog to C's __FILE__.

The behavior of Python's __file__ is much different than C's __FILE__. The C version will give you the original path of the source file. This is useful in logging errors and knowing which source file has the bug.

Python's __file__ only gives you the name of the currently executing file, which may not be very useful in log output.

Todd
  • 4,669
  • 1
  • 22
  • 30
  • 2
    This worksforme also when python is embedded in another application – sdaau Jan 11 '19 at 22:03
  • I've had better luck with this than the `os.path.dirname(os.path.realpath(...))` method. – Mr. S Jun 19 '19 at 15:58
  • 1
    This should be the top answer. – 183.amir May 25 '20 at 17:31
  • Can't get it work with Cython with Python 2.7 ``` File "/usr/lib/python2.7/inspect.py", line 419, in getfile 'function, traceback, frame, or code object'.format(object)) TypeError: at 0xb6663e30> is not a module, class, method, function, traceback, frame, or code object ``` – BrendanSimon Aug 03 '23 at 02:53
24

change your codes as follows! it works for me. `

os.path.dirname(os.path.abspath("__file__"))
Rahul Agarwal
  • 4,034
  • 7
  • 27
  • 51
Jojo Josiane
  • 419
  • 4
  • 3
  • 14
    I think you are actually using `os.getcwd()`, according to [doc](https://docs.python.org/3/library/os.path.html#os.path.abspath), and the `"__file__"` is meaningless. – davidlatwe Sep 06 '18 at 04:58
  • 28
    Why does this have upvotes? That many people took this, and because it got rid of an unhandled exception, they assumed it was correct?? **This is not a correct solution people**. What it's doing is saying that you have a file named literally, "`__file__`" and you prepend what folder it could be in **if it existed!** – Todd Feb 22 '20 at 19:37
  • 3
    This, apparently, works because iPython fails to find `os.path.dirname( os.path.abspath( os.getcwd() + "\_file_"))` and shortens it to just `os.getcwd()`. – Rustam A. Feb 01 '21 at 21:57
  • This code wasn't tested in the same context...that's why it didn't produce the same error – RexBarker Sep 16 '21 at 21:13
14

If you're using the code inside a .py file: Use os.path.abspath(__file__) If you're using the code on a script directly or in Jupyter Notebooks: Put the file inside double-quotes. os.path.abspath("__file__")

Brian Koech
  • 183
  • 1
  • 5
  • Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Mar 15 '22 at 04:28
10

Are you using the interactive interpreter? You can use

sys.argv[0]

You should read: How do I get the path of the current executed file in Python?

Community
  • 1
  • 1
Eloims
  • 5,106
  • 4
  • 25
  • 41
  • fd = os.path.dirname(os.path.realpath(__file__)) nd printing it printed .../../folder1/ but cwd = os.path.dirname(os.path.realpath(sys.argv[0])) >>> print cwd prints ../../ – bruceparker Feb 20 '15 at 16:43
  • 8
    this will give the path to the binary python that launched the shell, NOT the current working directory – hobs Aug 04 '16 at 05:33
  • 1
    it should be `argv[1]` instead of `argv[0]` – plustar Nov 20 '18 at 07:47
9

If all you are looking for is to get your current working directory os.getcwd() will give you the same thing as os.path.dirname(__file__) as long as you have not changed the working directory elsewhere in your code. os.getcwd() also works in interactive mode.

So os.path.join(os.path.dirname(__file__)) becomes os.path.join(os.getcwd())

Community
  • 1
  • 1
Andrew Fallgren
  • 151
  • 1
  • 3
  • This is a winner – Shawn Jan 21 '19 at 22:01
  • 7
    This answer **isn't correct**. `os.path.dirname(__file__)` doesn't report the same thing as `os.getcwd()`. What it gives you is the dir name of the file. If that turns out to match `os.getcwd()` it's merely a coincidence. – Todd Mar 05 '20 at 20:44
7

You will get this if you are running the commands from the python shell:

>>> __file__
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name '__file__' is not defined

You need to execute the file directly, by passing it in as an argument to the python command:

$ python somefile.py

In your case, it should really be python setup.py install

Burhan Khalid
  • 169,990
  • 18
  • 245
  • 284
3

If you're exec'ing a file via command line, you can use this hack

import traceback

def get_this_filename():
    try:
        raise NotImplementedError("No error")
    except Exception as e:
        exc_type, exc_value, exc_traceback = sys.exc_info()
        filename = traceback.extract_tb(exc_traceback)[-1].filename
    return filename

This worked for me in the UnrealEnginePython console, calling py.exec myfile.py

crizCraig
  • 8,487
  • 6
  • 54
  • 53
1

if you are using jupyter notebook like:

MODEL_NAME = os.path.basename(file)[:-3]

---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
<ipython-input-10-f391bbbab00d> in <module>
----> 1 MODEL_NAME = os.path.basename(__file__)[:-3]

NameError: name '__file__' is not defined

you should place a ' ! ' in front like this

!MODEL_NAME = os.path.basename(__file__)[:-3]

/bin/bash: -c: line 0: syntax error near unexpected token `('
/bin/bash: -c: line 0: `MODEL_NAME = os.path.basename(__file__)[:-3]'

done.....

Oscar Rangel
  • 848
  • 1
  • 10
  • 18
0

I'm having exacty the same problem and using probably the same tutorial. The function definition:

def read(*rnames):
    return open(os.path.join(os.path.dirname(__file__), *rnames)).read()

is buggy, since os.path.dirname(__file__) will not return what you need. Try replacing os.path.dirname(__file__) with os.path.dirname(os.path.abspath(__file__)):

def read(*rnames):
    return open(os.path.join(os.path.dirname(os.path.abspath(__file__)), *rnames)).read()

I've just posted Andrew that the code snippet in current docs don't work, hopefully, it'll be corrected.

ducin
  • 25,621
  • 41
  • 157
  • 256
0

I think you can do this which get your local file path

if not os.path.isdir(f_dir):
    os.mkdirs(f_dir)

try:
    approot = os.path.dirname(os.path.abspath(__file__))
except NameError:
    approot = os.path.dirname(os.path.abspath(sys.argv[1]))
    my_dir= os.path.join(approot, 'f_dir')
Hamilton
  • 620
  • 2
  • 14
  • 32
0

Working in a jupyter notebook it is convenient to set a workspace according to the script you are working on:

import os
import sys
os.chdir(Path(os.path.realpath('__file__')).parents[0])
sys.path.append(Path(os.path.realpath('__file__')).parents[0])
aljoshoh
  • 1
  • 1
0

The globals() built-in function can be used to test the condition:

if "__file__" in globals():
    path = os.path.join(os.path.dirname(globals()["__file__"])

Or if __file__ really needs to be set to some value:

if "__file__" not in globals():
    __file__ = "/maybe/it/is/here.py"

however, I don't recommend this, as it can lead to unexpected outcomes with interactive sessions.

Mike T
  • 41,085
  • 18
  • 152
  • 203