python NameError: ไม่ได้กำหนดชื่อโกลบอล '__file__'


112

เมื่อฉันเรียกใช้รหัสนี้ใน python 2.7 ฉันได้รับข้อผิดพลาดนี้:

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

รหัสคือ:

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

คำตอบ:


134

ข้อผิดพลาดนี้เกิดขึ้นเมื่อคุณต่อท้ายบรรทัดนี้os.path.join(os.path.dirname(__file__))ใน python โต้ตอบเชลล์

Python Shellตรวจไม่พบเส้นทางของไฟล์ปัจจุบัน__file__และเกี่ยวข้องกับfilepathที่คุณเพิ่มบรรทัดนี้

คุณควรเขียนบรรทัดนี้os.path.join(os.path.dirname(__file__))ในfile.py. แล้วเรียกใช้python file.pyมันใช้งานได้เพราะใช้พา ธ ไฟล์ของคุณ


8
ประสบการณ์ของฉัน แต่จะทำให้มันทำงานภายในเชลล์ได้อย่างไร?
s2t2

1
แต่หากต้องการเรียกใช้file.pyสคริปต์คุณจะต้องวางไว้ในไดเร็กทอรีเดียวกับสคริปต์ของคุณ ดังนั้นคุณต้องย้ายไปที่ไดเรกทอรีนี้ก่อนที่จะเรียกใช้file.py...
ztyh

ดังนั้น Emacs จึงใช้เชลล์แบบโต้ตอบเมื่อคุณ Cc Cp? งูหลามเชลล์ มีวิธีใช้เชลล์นี้เหมือนกับว่าเป็นเทอร์มินัลที่เรียกใช้ไฟล์หรือไม่ มี 3 ตัวเลือกสำหรับการรันเชลล์: CMD DEDICATED SHOW หนึ่งในนั้นจะทำสิ่งนี้ได้หรือไม่?
sinekonata

18

ฉันมีปัญหาเดียวกันกับ PyInstaller และ Py2exe ดังนั้นฉันจึงพบความละเอียดใน FAQ จาก cx-freeze

เมื่อใช้สคริปต์ของคุณจากคอนโซลหรือเป็นแอปพลิเคชันฟังก์ชันที่อยู่ในที่นี้จะส่ง "เส้นทางการดำเนินการ" ให้คุณไม่ใช่ "เส้นทางไฟล์จริง":

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

ที่มา:
http://cx-freeze.readthedocs.org/en/latest/faq.html

บรรทัดเก่าของคุณ (คำถามเริ่มต้น):

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

แทนที่บรรทัดรหัสของคุณด้วยข้อมูลโค้ดต่อไปนี้

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)

ด้วยรหัสด้านบนคุณสามารถเพิ่มแอปพลิเคชันของคุณไปยังเส้นทางของระบบปฏิบัติการของคุณคุณสามารถเรียกใช้งานได้ทุกที่โดยไม่มีปัญหาว่าแอปของคุณไม่พบไฟล์ข้อมูล / การกำหนดค่า

ทดสอบด้วย python:

  • 3.3.4
  • 2.7.13

11

เปลี่ยนรหัสของคุณดังนี้! มันได้ผลสำหรับฉัน `

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

7
ฉันคิดว่าคุณใช้จริงos.getcwd()ตามเอกสารและ"__file__"ไม่มีความหมาย
davidlatwe

5
เหตุใดจึงมีการโหวตเพิ่มขึ้น ที่หลายคนรับสิ่งนี้และเพราะมันกำจัดข้อยกเว้นที่ไม่สามารถจัดการได้พวกเขาจึงคิดว่ามันถูกต้อง ?? นี้ไม่ได้เป็นคนวิธีที่ถูกต้อง สิ่งที่ทำคือบอกว่าคุณมีไฟล์ชื่อตัวอักษร " __file__" และคุณนำหน้าโฟลเดอร์ที่อาจอยู่ในนั้นถ้ามีอยู่!
ทอดด์

11

ฉันเจอกรณีที่__file__ไม่ได้ผลตามที่คาดไว้ แต่สิ่งต่อไปนี้ยังไม่ทำให้ฉันล้มเหลว:

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

__FILE__นี่คือสิ่งที่ใกล้เคียงกับอนาล็อกงูหลามซี

ลักษณะการทำงานของ Python __file__แตกต่างจาก C __FILE__มาก เวอร์ชัน C จะให้เส้นทางดั้งเดิมของไฟล์ต้นฉบับแก่คุณ สิ่งนี้มีประโยชน์ในการบันทึกข้อผิดพลาดและการทราบว่าซอร์สไฟล์ใดมีจุดบกพร่อง

Python __file__ให้ชื่อไฟล์ที่กำลังดำเนินการอยู่เท่านั้นซึ่งอาจไม่มีประโยชน์มากนักในเอาต์พุตบันทึก


2
สิ่งนี้ใช้ได้ผลเช่นกันเมื่อ python ถูกฝังในแอปพลิเคชันอื่น
sdaau

ฉันโชคดีกว่าos.path.dirname(os.path.realpath(...))วิธีนี้
นาย S

1
นี่น่าจะเป็นคำตอบอันดับต้น ๆ
183.amir

9

คุณใช้ล่ามโต้ตอบหรือไม่ คุณสามารถใช้ได้

sys.argv[0]

คุณควรอ่าน: ฉันจะรับเส้นทางของไฟล์ที่เรียกใช้งานปัจจุบันใน Python ได้อย่างไร


fd = os.path.dirname (os.path.realpath ( ไฟล์ )) nd พิมพ์ออกมา ... / .. / folder1 / แต่ cwd = os.path.dirname (os.path.realpath (sys.argv [0 ])) >>> พิมพ์
cwd

7
สิ่งนี้จะให้เส้นทางไปยังไพ ธ อนไบนารีที่เปิดตัวเชลล์ไม่ใช่ไดเร็กทอรีการทำงานปัจจุบัน
hobs

ควรจะเป็นargv[1]แทนargv[0]
plustar

8

ฉันแก้ไขได้โดยใช้ไฟล์เป็นสตริงเช่นใส่"__file__"(พร้อมกับเครื่องหมายคำพูด!) แทน__file__

สิ่งนี้ใช้ได้ดีสำหรับฉัน:

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

8
นี่ใช้ได้ผลจริง แต่ฉันไม่สามารถเข้าใจได้ว่าทำไม เหตุใด"__file__"ระหว่างเครื่องหมายคำพูดจึงแตกต่างจากการ__file__ไม่มีเครื่องหมายคำพูด
Gio

5
เนื่องจากไม่ได้อ้างอิงตัวแปรส่วนกลางที่หายไป แต่จะถือว่าสตริง " file " เป็นส่วนหนึ่งของเส้นทาง
JoshVarty

42
สิ่งนี้ไม่ส่งคืนไดเร็กทอรีที่ไฟล์อยู่ แต่เพียงแค่ส่งคืนไดเร็กทอรีการทำงานปัจจุบัน (ที่ซึ่งเรียกว่า python) -1
Xiangyu

8
ชื่อไฟล์ใด ๆ จะแทนที่"__file__". เช่นrealpath('nonexistentfile.whatever').
เตา

35
คำตอบนี้ควรถูกลบออกเนื่องจากไม่ถูกต้องและทำให้เข้าใจผิด ความจริงที่ได้รับการโหวตสูงมากจึงค่อนข้างน่ากังวล ...
Cas

7

หากสิ่งที่คุณกำลังมองหาคือการได้รับไดเร็กทอรีการทำงานปัจจุบันของคุณos.getcwd()จะให้สิ่งเดียวกันos.path.dirname(__file__)ตราบเท่าที่คุณไม่ได้เปลี่ยนไดเร็กทอรีการทำงานที่อื่นในโค้ดของคุณ os.getcwd()ยังทำงานในโหมดโต้ตอบ

ดังนั้น os.path.join(os.path.dirname(__file__)) จะกลายเป็น os.path.join(os.getcwd())


นี่คือผู้ชนะ
Shawn

1
คำตอบนี้ไม่ถูกต้อง ไม่รายงานสิ่งเดียวกับos.path.dirname(__file__) os.getcwd()สิ่งที่ให้คุณคือชื่อ dir ของไฟล์ ถ้ามันออกมาตรงกันos.getcwd()มันเป็นแค่เรื่องบังเอิญ
ทอดด์

4

คุณจะได้รับสิ่งนี้หากคุณใช้คำสั่งจาก python shell:

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

คุณต้องเรียกใช้ไฟล์โดยตรงโดยส่งเป็นอาร์กิวเมนต์ของpythonคำสั่ง:

$ python somefile.py

ในกรณีของคุณควรเป็นอย่างนั้นจริงๆ python setup.py install


2

สิ่งที่ทำได้คือใช้สิ่งต่อไปนี้

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

ทราบที่นี่ที่ใช้สตริงไม่แน่นอนหมายถึงตัวแปรที่เกิดขึ้นจริง'__file__' __file__ทดสอบเองได้แน่นอน ..

โบนัสเพิ่มเติมของโซลูชันนี้คือความยืดหยุ่นเมื่อคุณรันสคริปต์บางส่วนแบบโต้ตอบ (เช่นเพื่อทดสอบ / พัฒนา) และสามารถรันผ่าน commandline


เกี่ยวกับบันทึกย่อของคุณในขณะที่'__file__'เป็นชื่อตัวแปรที่ถูกต้องและifเงื่อนไขของคุณจะเป็นจริง แต่os.path.realpath('__file__')จะส่งคืนเส้นทางปลอมที่ถือว่า'__file__'เป็นชื่อของไฟล์ หากสิ่งที่คุณต้องการคือไดเรกทอรีหลักผ่านทางos.path.dirname()คุณก็สบายดี - แต่นั่นคือ "แฮ็ก" @zwep
Todd

นอกจากนี้การอ้างอิง__file__จากภายในไฟล์ต้นฉบับจะได้รับเส้นทางของไฟล์ที่ใช้ - ไม่ใช่สิ่งเดียวกับos.getcwd()ไฟล์. จะไม่เป็นwk_dirไดเรกทอรีงานของคุณเสมอไป
ทอดด์

2

หากคุณกำลังดำเนินการไฟล์ผ่านทางบรรทัดคำสั่งคุณสามารถใช้แฮ็คนี้ได้

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

สิ่งนี้ใช้ได้ผลสำหรับฉันในคอนโซล UnrealEnginePython การโทร py.exec myfile.py


1

ฉันมีปัญหาเดียวกันในสมุดบันทึก Jupyter ในขณะที่ฉันใช้ 'os.path.split (os.path.realpath ( ไฟล์ ))' โน้ตบุ๊กเกิดข้อผิดพลาด

ฉันจึงใช้ ' ไฟล์ ' มันทำงานได้อย่างสมบูรณ์แบบ


0

ฉันมี exacty ปัญหาเดียวกันและใช้อาจกวดวิชาเดียวกัน นิยามฟังก์ชัน:

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

เป็นรถเนื่องจากos.path.dirname(__file__)จะไม่คืนสิ่งที่คุณต้องการ ลองแทนที่os.path.dirname(__file__)ด้วยos.path.dirname(os.path.abspath(__file__)):

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

ฉันเพิ่งโพสต์แอนดรูว์ว่าข้อมูลโค้ดในเอกสารปัจจุบันใช้ไม่ได้หวังว่าจะได้รับการแก้ไข

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.