python NameError: nome global '__file__' não está definido


112

Quando executo este código em python 2.7, recebo este erro:

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

o código é:

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']
      )

Respostas:


134

Este erro ocorre quando você anexa esta linha os.path.join(os.path.dirname(__file__))no shell interativo do python.

Python Shellnão detecta o caminho do arquivo atual __file__e está relacionado ao seu filepathno qual você adicionou esta linha

Então você deve escrever esta linha os.path.join(os.path.dirname(__file__))no file.py. e, em seguida python file.py, execute , ele funciona porque leva o seu caminho de arquivo.


8
exatamente minha experiência. mas como fazê-lo funcionar dentro de um shell?
s2t2

1
Mas para rodar a file.pypartir de um script, você o colocaria no mesmo diretório do seu script, por exemplo. Portanto, você precisa mover para este diretório antes de executar file.py... Então, ainda algo melhor é procurado.
ztyh

Então o Emacs usa um shell interativo quando você Cc Cp? python-shell. Existe uma maneira de usar este shell como se fosse um terminal executando o arquivo? Existem 3 opções para executar o shell: CMD DEDICATED SHOW Será que um deles faria isso?
sinekonata

18

Eu tive o mesmo problema com o PyInstaller e o Py2exe, então encontrei a resolução no FAQ do cx-freeze.

Ao usar seu script do console ou como um aplicativo, as funções a seguir fornecerão o "caminho de execução", não o "caminho real do arquivo":

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

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

Sua linha antiga (pergunta inicial):

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

Substitua sua linha de código pelo seguinte 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)

Com o código acima, você pode adicionar seu aplicativo ao caminho do seu sistema operacional, você pode executá-lo em qualquer lugar sem o problema de seu aplicativo não conseguir encontrar seus arquivos de dados / configuração.

Testado com python:

  • 3.3.4
  • 2.7.13

12

mude seus códigos da seguinte maneira! funciona para mim. `

os.path.dirname(os.path.abspath("__file__"))

7
Acho que você está realmente usando os.getcwd(), de acordo com o doc , e "__file__"não faz sentido.
davidlatwe

5
Por que isso tem votos positivos? Muitas pessoas pegaram isso e, como eliminou uma exceção não tratada, presumiram que estava correto ?? Esta não é uma solução correta gente . O que ele está fazendo é dizer que você tem um arquivo chamado literalmente " __file__" e você adiciona a pasta onde ele poderia estar, se existisse!
Todd

11

Já encontrei casos em __file__que não funciona conforme o esperado. Mas o seguinte não me falhou até agora:

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

Esta é a coisa mais próxima de um análogo de Python para C do __FILE__.

O comportamento do Python __file__é muito diferente do C de __FILE__. A versão C fornecerá o caminho original do arquivo de origem. Isso é útil para registrar erros e saber qual arquivo de origem contém o bug.

O Python __file__fornece apenas o nome do arquivo atualmente em execução, o que pode não ser muito útil na saída do log.


2
Este workforme também quando o python estiver embutido em outro aplicativo
sdaau

Tive mais sorte com isso do que com o os.path.dirname(os.path.realpath(...))método.
Sr. S

1
Esta deve ser a melhor resposta.
183.amir

9

Você está usando o intérprete interativo? Você pode usar

sys.argv[0]

Você deve ler: Como obtenho o caminho do arquivo executado no Python?


fd = os.path.dirname (os.path.realpath ( file )) e imprimi-lo impresso ... / .. / folder1 / mas cwd = os.path.dirname (os.path.realpath (sys.argv [0 ])) >>> imprimir cópias cwd ../../
bruceparker

7
isso fornecerá o caminho para o python binário que lançou o shell, NÃO o diretório de trabalho atual
hobs

deveria ser em argv[1]vez deargv[0]
plustar

9

Eu resolvi isso tratando o arquivo como uma string, ou seja, colocado "__file__"(junto com as aspas!) Em vez de__file__

Este trabalho é bom para mim:

wk_dir = os.path.dirname(os.path.realpath('__file__'))

8
Isso realmente funciona, mas não consigo entender por quê. Por que o "__file__"tratamento entre aspas é diferente do que __file__sem aspas?
Gio

5
Porque não faz referência à variável global ausente. Em vez disso, trata a string ' arquivo ' como parte do caminho.
JoshVarty de

42
Isso não retorna o diretório onde o arquivo está localizado, mas apenas o diretório de trabalho atual (onde o python é chamado). -1
Xiangyu

8
Qualquer nome de arquivo servirá no lugar de "__file__". Ex realpath('nonexistentfile.whatever').
horas de

35
Esta resposta realmente deve ser removida, pois é incorreta e enganosa. O fato de ter uma votação tão positiva é bastante preocupante ...
Cas

6

Se tudo o que você está procurando é obter seu diretório de trabalho atual, os.getcwd()isso lhe dará a mesma coisa os.path.dirname(__file__), contanto que você não tenha alterado o diretório de trabalho em outro lugar em seu código. os.getcwd()também funciona no modo interativo.

Então os.path.join(os.path.dirname(__file__)) se torna os.path.join(os.getcwd())


Este é um vencedor
Shawn

1
Esta resposta não está correta . os.path.dirname(__file__)não relata a mesma coisa que os.getcwd(). O que ele fornece é o nome do diretório do arquivo. Se isso corresponder os.getcwd(), é apenas uma coincidência.
Todd

4

Você obterá isso se estiver executando os comandos do shell Python:

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

Você precisa executar o arquivo diretamente, passando-o como um argumento para o pythoncomando:

$ python somefile.py

No seu caso, deveria realmente ser python setup.py install


2

O que você pode fazer é usar o seguinte

import os
if '__file__' in vars():
    wk_dir = os.path.dirname(os.path.realpath('__file__'))
else:
    print('We are running the script interactively')

Observe aqui que usar a string '__file__'realmente se refere à variável real __file__. Você pode testar você mesmo, é claro ..

O bônus adicional desta solução é a flexibilidade quando você está executando um script parcialmente interativamente (por exemplo, para testá-lo / desenvolvê-lo), e pode executá-lo através da linha de comando


Em relação à sua nota, while '__file__'é um nome de variável válido, e sua ifcondição for verdadeira, os.path.realpath('__file__')retornará um caminho falso tratando '__file__'como se fosse o nome do arquivo. Se tudo que você precisa é seu diretório pai via os.path.dirname(), tudo bem - mas isso é um "hack". @zwep
Todd

Além disso, a referência a __file__partir de um arquivo de origem obterá o caminho do arquivo no qual é usado - não é a mesma coisa que os.getcwd(). Nem sempre será seu wk_dir- ou diretório de trabalho.
Todd

2

Se você está executando um arquivo via linha de comando, você pode usar este 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

Isso funcionou para mim no console UnrealEnginePython, chamando py.exec myfile.py


1

Eu tive o mesmo problema no notebook Jupyter. Enquanto eu usava 'os.path.split (os.path.realpath ( file ))', o bloco de notas apresentava um erro.

Portanto, usei ' arquivo '. Funcionou perfeitamente.


0

Estou tendo exatamente o mesmo problema e provavelmente usando o mesmo tutorial . A definição da função:

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

é bugado, pois os.path.dirname(__file__)não retornará o que você precisa. Tente substituir os.path.dirname(__file__)por os.path.dirname(os.path.abspath(__file__)):

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

Acabei de postar para Andrew que o trecho de código nos documentos atuais não funciona, espero que seja corrigido.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.