python NameError: global name '__file__' không được xác định


112

Khi tôi chạy mã này trong python 2.7, tôi gặp lỗi này:

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

mã là:

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

Câu trả lời:


134

Lỗi này xảy ra khi bạn nối dòng này os.path.join(os.path.dirname(__file__))trong trình bao tương tác python.

Python Shellkhông phát hiện ra đường dẫn tệp hiện tại __file__và nó liên quan đến đường dẫn của bạn filepathmà bạn đã thêm dòng này

Vì vậy, bạn nên viết dòng này os.path.join(os.path.dirname(__file__))vào file.py. và sau đó chạy python file.py, Nó hoạt động vì nó sử dụng đường dẫn tệp của bạn.


8
chính xác là kinh nghiệm của tôi. nhưng làm thế nào để làm cho nó hoạt động trong một shell?
s2t2

1
Nhưng để chạy file.pytừ một tập lệnh, bạn sẽ đặt nó trong cùng một thư mục với tập lệnh của bạn chẳng hạn. Vì vậy, bạn cần phải di chuyển đến thư mục này trước khi chạy file.py... Vì vậy, vẫn còn một cái gì đó tốt hơn được tìm kiếm.
ztyh

Vì vậy, Emacs sử dụng một shell tương tác khi bạn Cc Cp? vỏ trăn. Có cách nào để sử dụng trình bao này như thể nó là một thiết bị đầu cuối chạy tệp không? Có 3 tùy chọn để chạy shell: CMD DEDICATED SHOW Liệu một trong số họ có làm được điều này không?
sinekonata

18

Tôi đã gặp vấn đề tương tự với PyInstaller và Py2exe nên tôi đã tìm ra giải pháp trên Câu hỏi thường gặp từ cx-freeze.

Khi sử dụng tập lệnh của bạn từ bảng điều khiển hoặc dưới dạng ứng dụng, các chức năng dưới đây sẽ cung cấp cho bạn "đường dẫn thực thi", không phải "đường dẫn tệp thực":

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

Nguồn:
http://cx-freeze.readthedocs.org/en/latest/faq.html

Dòng cũ của bạn (câu hỏi đầu tiên):

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

Thay thế dòng mã của bạn bằng đoạn mã sau.

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)

Với đoạn mã trên, bạn có thể thêm ứng dụng của mình vào đường dẫn của hệ điều hành, bạn có thể thực thi nó ở bất cứ đâu mà không gặp vấn đề ứng dụng của bạn không thể tìm thấy tệp dữ liệu / cấu hình của nó.

Đã thử nghiệm với python:

  • 3.3.4
  • 2.7.13

12

thay đổi mã của bạn như sau! nó hoạt động cho tôi. `

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

7
Tôi nghĩ rằng bạn đang thực sự sử dụng os.getcwd(), theo bác , và "__file__"nó là vô nghĩa.
davidlatwe

5
Tại sao điều này có lượt ủng hộ? Nhiều người đã lấy điều này, và vì nó đã loại bỏ một ngoại lệ không được giải quyết, họ cho rằng nó đúng ?? Đây không phải là một giải pháp chính xác mọi người . Những gì nó đang làm là nói rằng bạn có một tệp được đặt tên theo nghĩa đen, " __file__" và bạn thêm trước nó vào thư mục nào nếu nó tồn tại!
Todd

11

Tôi đã gặp phải những trường hợp __file__không hoạt động như mong đợi. Nhưng những điều sau vẫn chưa làm tôi thất vọng cho đến nay:

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

Đây là điều gần gũi nhất với một analog Python để C __FILE__.

Hành vi của Python __file__là nhiều khác biệt so với C __FILE__. Phiên bản C sẽ cung cấp cho bạn đường dẫn ban đầu của tệp nguồn. Điều này rất hữu ích trong việc ghi lại lỗi và biết được tệp nguồn nào có lỗi.

Python __file__chỉ cung cấp cho bạn tên của tệp hiện đang thực thi, có thể không hữu ích lắm trong đầu ra nhật ký.


2
Điều này cũng hoạt động khi python được nhúng vào một ứng dụng khác
sdaau

Tôi đã gặp may mắn với điều này hơn là os.path.dirname(os.path.realpath(...))phương pháp.
Ông S

1
Đây phải là câu trả lời hàng đầu.
183.amir

9

Bạn có đang sử dụng trình thông dịch tương tác không? Bạn có thể dùng

sys.argv[0]

Bạn nên đọc: Làm cách nào để lấy đường dẫn của tệp được thực thi hiện tại bằng Python?


fd = os.path.dirname (os.path.realpath ( file )) và in nó ra ... / .. / folder1 / but cwd = os.path.dirname (os.path.realpath (sys.argv [0 ])) >>> in bản in
cwd

7
điều này sẽ cung cấp đường dẫn đến python nhị phân đã khởi chạy trình bao, KHÔNG phải thư mục làm việc hiện tại
hobs

nó nên được argv[1]thay vìargv[0]
plustar

9

Tôi đã giải quyết nó bằng cách coi tệp là một chuỗi, tức là đặt "__file__"(cùng với dấu ngoặc kép!) Thay vì__file__

Cái này làm việc tốt cho tôi:

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

8
Điều này thực sự hiệu quả, nhưng tôi không thể hiểu tại sao. Tại sao "__file__"giữa các dấu ngoặc kép được xử lý khác với __file__không có dấu ngoặc kép?
Gio

5
Vì nó không tham chiếu đến biến toàn cục bị thiếu. Thay vào đó, nó coi chuỗi ' tệp ' như một phần của đường dẫn.
JoshVarty

42
Thao tác này không trả về thư mục chứa tệp mà chỉ trả về thư mục làm việc hiện tại (nơi python được gọi). -1
Xiangyu

8
Bất kỳ tên tệp nào sẽ thay thế cho "__file__". Vd realpath('nonexistentfile.whatever').
hobs

35
Câu trả lời này thực sự nên bị loại bỏ vì nó không chính xác và gây hiểu lầm. Thực tế là nó được ủng hộ rất cao là điều khá đáng lo ngại ...
Cas

6

Nếu tất cả những gì bạn đang tìm kiếm là để có được thư mục làm việc hiện tại của bạn os.getcwd()thì sẽ cung cấp cho bạn điều tương tự os.path.dirname(__file__)miễn là bạn không thay đổi thư mục làm việc ở nơi khác trong mã của mình. os.getcwd()cũng hoạt động ở chế độ tương tác.

Vì vậy, os.path.join(os.path.dirname(__file__)) trở thành os.path.join(os.getcwd())


Đây là một người chiến thắng
Shawn

1
Câu trả lời này không đúng . os.path.dirname(__file__)không báo cáo điều tương tự như os.getcwd(). Những gì nó cung cấp cho bạn là tên dir của tệp. Nếu điều đó trở os.getcwd()nên trùng khớp thì đó chỉ là một sự trùng hợp.
Todd

4

Bạn sẽ nhận được điều này nếu bạn đang chạy các lệnh từ python shell:

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

Bạn cần thực thi tệp trực tiếp, bằng cách chuyển nó vào làm đối số cho pythonlệnh:

$ python somefile.py

Trong trường hợp của bạn, nó thực sự nên python setup.py install


2

Những gì bạn có thể làm là sử dụng

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

Lưu ý ở đây rằng việc sử dụng chuỗi '__file__'thực sự tham chiếu đến biến thực tế __file__. Tất nhiên, bạn có thể tự mình kiểm tra điều này ..

Phần thưởng bổ sung của giải pháp này là tính linh hoạt khi bạn đang chạy một tập lệnh tương tác một phần (ví dụ: để kiểm tra / phát triển nó) và có thể chạy nó qua dòng lệnh


Về ghi chú của bạn, while '__file__'là một tên biến hợp lệ và ifđiều kiện của bạn là đúng, os.path.realpath('__file__')sẽ trả về một đường dẫn giả mạo '__file__'như thể đó là tên của tệp. Nếu tất cả những gì bạn cần là thư mục mẹ của nó thông qua os.path.dirname(), thì bạn vẫn ổn - nhưng đó là "hack". @zwep
Todd

Ngoài ra, việc tham chiếu __file__từ bên trong tệp nguồn sẽ nhận được đường dẫn của tệp mà nó được sử dụng - nó không giống như vậy os.getcwd(). Nó sẽ không phải lúc nào cũng là wk_dir- hoặc thư mục công việc của bạn .
Todd

2

Nếu bạn đang thực thi một tệp qua dòng lệnh, bạn có thể sử dụng bản hack này

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

Điều này đã làm việc cho tôi trong bảng điều khiển UnrealEnginePython, gọi py.exec myfile.py


1

Tôi đã gặp vấn đề tương tự trong sổ ghi chép Jupyter. Trong khi tôi sử dụng 'os.path.split (os.path.realpath ( file ))', sổ ghi chép đã gặp lỗi.

Do đó, tôi đã sử dụng ' tệp '. Nó hoạt động hoàn hảo.


0

Tôi gặp chính xác cùng một vấn đề và có lẽ đang sử dụng cùng một hướng dẫn . Định nghĩa hàm:

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

là lỗi, vì os.path.dirname(__file__)sẽ không trả lại những gì bạn cần. Hãy thử thay thế os.path.dirname(__file__)bằng os.path.dirname(os.path.abspath(__file__)):

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

Tôi vừa đăng cho Andrew rằng đoạn mã trong tài liệu hiện tại không hoạt động, hy vọng, đoạn mã sẽ được sửa chữa.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.