__pycache__ คืออะไร


651

จากสิ่งที่ฉันเข้าใจแคชคือไฟล์ที่เข้ารหัสของไฟล์ที่คล้ายกัน

เราจะทำอย่างไรกับ__pycache__โฟลเดอร์? มันเป็นสิ่งที่เราให้กับผู้คนแทนที่จะเป็นซอร์สโค้ดของเราหรือไม่ มันเป็นเพียงข้อมูลอินพุตของฉันหรือไม่ โฟลเดอร์นี้ยังคงถูกสร้างขึ้นมาเพื่ออะไร


29
"เป็นสิ่งที่เราให้คนอื่นแทนที่จะเป็นซอร์สโค้ดของเราหรือไม่" - ไม่คุณให้รหัสแหล่งที่มาแก่พวกเขาในแพ็คเกจที่ติดตั้งได้ดีดังนั้นมันจึงใช้งานง่าย
Lennart Regebro

79
ยังไม่มีใครพูดถึง แต่คำจำกัดความของแคชของคุณนั้นแปลกประหลาด แคชค่อนข้างเพียงองค์ประกอบที่จัดเก็บข้อมูลเพื่อการร้องขอในอนาคตสำหรับข้อมูลที่สามารถทำหน้าที่ได้เร็วขึ้น
Ricardo Cruz


1
เนื่องจากPython 3.8คุณสามารถใช้ตัวแปรสภาพแวดล้อมเพื่อเปลี่ยนตำแหน่งสำหรับไดเรกทอรีแคชที่น่ารำคาญ: stackoverflow.com/a/57414308/1612318
Rotareti

แคชคือสิ่งที่เก็บสำเนาของสิ่งต่าง ๆ ในกรณีที่คุณต้องการอีกครั้งเพื่อช่วยให้คุณไม่ต้องกลับไปที่เดิมเพื่อรับมัน มันถูกออกแบบมาให้เร็วกว่าไปยังที่ดั้งเดิม มันอาจเร็วกว่าเพราะไม่จำเป็นต้องประมวลผลล่วงหน้าหรือรวบรวมข้อมูล หรืออาจเป็นที่เก็บข้อมูลที่เร็วกว่าเช่นแคชดิสก์ใน RAM หรือเว็บแคชบนดิสก์ภายในเครื่อง มันไม่ได้เข้ารหัสตามธรรมชาติ (แม้ว่าบางครั้งมันอาจจะเป็น) และมันก็ไม่ได้เป็น "ไฟล์ของไฟล์ที่คล้ายกัน" - มันสามารถเป็นไฟล์, โหลดไฟล์, บล็อกของ RAM ฯลฯ
rjmunro

คำตอบ:


518

เมื่อคุณเรียกใช้โปรแกรมในไพ ธ อนตัวแปลจะคอมไพล์ให้กับ bytecode ก่อน (นี่เป็นการทำ oversimplification) และเก็บไว้ใน__pycache__โฟลเดอร์ หากคุณมองเข้าไปในนั้นคุณจะพบไฟล์หลายไฟล์ที่แชร์ชื่อไฟล์. py ในโฟลเดอร์ของโครงการของคุณเฉพาะส่วนขยายเท่านั้นที่จะเป็น. pyc หรือ. pyo ไฟล์เหล่านี้เป็นไฟล์โปรแกรมของคุณที่คอมไพล์ด้วยคอมไพล์และปรับให้เหมาะสมตามลำดับ

ในฐานะโปรแกรมเมอร์คุณสามารถเพิกเฉยได้เลย ... สิ่งที่ทำคือทำให้โปรแกรมของคุณเริ่มต้นได้เร็วขึ้นเล็กน้อย เมื่อสคริปต์ของคุณเปลี่ยนพวกเขาจะถูกคอมไพล์ใหม่และหากคุณลบไฟล์หรือทั้งโฟลเดอร์และเรียกใช้โปรแกรมของคุณอีกครั้งสคริปต์จะปรากฏขึ้นอีกครั้ง (เว้นแต่คุณจะระงับพฤติกรรมนั้นโดยเฉพาะ)

หากคุณใช้ cpython (ซึ่งเป็นเรื่องธรรมดาที่สุดเนื่องจากเป็นการใช้งานอ้างอิง) และคุณไม่ต้องการโฟลเดอร์นั้นคุณสามารถระงับได้โดยเริ่มล่ามด้วยแฟล็ก -B เป็นต้น

python -B foo.py

ตัวเลือกอื่นดังที่บันทึกไว้โดย tcaswell คือการตั้งค่าตัวแปรสภาพแวดล้อมPYTHONDONTWRITEBYTECODEเป็นค่าใด ๆ (ตามหน้า man ของ python "สตริงที่ไม่ว่าง" ใด ๆ )


48
นอกจากนี้คุณยังสามารถเพิ่มตัวแปรสภาพแวดล้อมPYTHONDONTWRITEBYTECODE=<any_value>เพื่อระงับมันอย่างถาวร
Mark Tolonen

11
เพื่อชี้แจงเท่านั้นนี่คือ Python 3 เท่านั้นถูกต้องไหม
Joe J

11
@JoeJ ใช่ฉันคิดว่ามันเป็นเรื่องจริง python2วางไฟล์ที่คอมไพล์ในไดเรกทอรีเดียวกับต้นฉบับถ้าฉันไม่เข้าใจผิด
scott_fakename

27
หนึ่งข้อแม้สำคัญคือไฟล์แคช. pyc จะถูกใช้แทนไฟล์. py หากไฟล์. py หายไป ในทางปฏิบัติสิ่งนี้จะเกิดขึ้นเฉพาะเมื่อคุณลบโมดูล (หรือเปลี่ยนชื่อ) ดังนั้นมันจึงไม่ใช่เรื่องปกติ แต่ถ้ามีบางสิ่งที่ยังคงเป็น "ที่นั่น" หลังจากเกาศีรษะ -name * .pyc | xargs rm บนแหล่งที่มาของคุณน่าจะเป็นปฏิกิริยาแรกที่ดี
yacc143

34
find . -name '*.pyc' -deleteใช่ find มีการตั้งค่าสถานะเพื่อลบไฟล์ที่พบดังนั้นคุณไม่จำเป็นต้องใช้ xargs shananigans ใด ๆ
vlad-ardelean

174

__pycache__เป็นโฟลเดอร์ที่มีงูหลาม 3 bytecode รวบรวมและพร้อมที่จะดำเนินการ

ฉันไม่แนะนำให้ลบไฟล์เหล่านี้เป็นประจำหรือหยุดการสร้างระหว่างการพัฒนาเนื่องจากอาจส่งผลต่อประสิทธิภาพการทำงาน เพียงแค่มีคำสั่งแบบเรียกซ้ำพร้อม (ดูด้านล่าง) เพื่อล้างเมื่อจำเป็นเนื่องจาก bytecode สามารถค้างในกรณีขอบ (ดูความคิดเห็น)

Python โปรแกรมเมอร์ไม่สนใจ bytecode แน่นอน__pycache__และ*.pycเป็นบรรทัดทั่วไปที่จะเห็นใน.gitignoreไฟล์ bytecode ไม่ได้หมายความว่าการจัดจำหน่ายและสามารถถอดประกอบโดยใช้โมดูลdis


หากคุณใช้ OS X คุณสามารถซ่อนโฟลเดอร์เหล่านี้ทั้งหมดในโครงการของคุณได้อย่างง่ายดายโดยการเรียกใช้คำสั่งต่อไปนี้จากโฟลเดอร์รูทของโครงการของคุณ

find . -name '__pycache__' -exec chflags hidden {} \;

แทนที่__pycache__ด้วย*.pycสำหรับ Python 2

ชุดนี้จะตั้งค่าสถานะในทุกไดเรกทอรี (ไฟล์. pyc) บอก Finder / Textmate 2 เพื่อแยกพวกเขาออกจากรายชื่อ ที่สำคัญรหัสไบต์อยู่ที่นั่นมันก็ซ่อนอยู่

รันคำสั่งอีกครั้งถ้าคุณสร้างโมดูลใหม่และต้องการที่จะซ่อนไบต์ใหม่หรือถ้าคุณลบไฟล์ bytecode ที่ซ่อนอยู่


ใน Windows คำสั่งเทียบเท่าอาจเป็น (ไม่ได้ทดสอบยินดีต้อนรับสคริปต์ชุด):

dir * /s/b | findstr __pycache__ | attrib +h +s +r

ซึ่งเหมือนกับการซ่อนโครงการโดยใช้การคลิกขวา> ซ่อน ...


การทดสอบหน่วยที่รันอยู่เป็นสถานการณ์หนึ่ง (ในความคิดเห็นเพิ่มเติม) ซึ่งการลบ*.pycไฟล์และ__pycache__โฟลเดอร์นั้นมีประโยชน์จริง ๆ ฉันใช้บรรทัดต่อไปนี้ในของฉัน~/.bash_profileและเพียงแค่เรียกใช้clเพื่อล้างข้อมูลเมื่อจำเป็น

alias cpy='find . -name "__pycache__" -delete'
alias cpc='find . -name "*.pyc"       -delete'
...
alias cl='cpy && cpc && ...'

สิ่งนี้จะไม่ถูกยกเลิกทุกครั้งที่คุณเรียกใช้รหัสหรือไม่
Holloway

2
@DoTheEvo: มันไม่ได้ถูกสร้างขึ้นดังนั้นจึงไม่มีการเร่งความเร็วในครั้งต่อไปที่โหลดโมดูล ไม่มีข้อผิดพลาดขึ้น
Petr Viktorin

7
นี่ไม่ใช่คำตอบที่ดี ผู้ถามต้องการทราบว่าไฟล์เหล่านี้มีไว้เพื่ออะไร คำตอบนี้บอกว่า "ไม่ต้องกังวลกับมัน" จากนั้นทำให้หายไป
น่าสนใจมี

36
รบกวนการลบเหล่านี้อย่างแน่นอน : มันไม่มีประโยชน์ Python จะไม่ตรวจจับการเปลี่ยนแปลงไฟล์อย่างมีความสุขและรันไฟล์แคชในหลาย ๆ สถานการณ์ผลักคุณขึ้นไปบนกำแพงด้วย "ทำไม f ถึงยังใช้งานไม่ได้ฉันเปลี่ยนรหัสทำไมมันยังล้มเหลวในการโทรที่ไม่มีอยู่" โดยเฉพาะอย่างยิ่งในกรอบการทดสอบ pycache-by-default นั้นเลวร้ายที่สุด
Kamermans 'Pomax' ของไมค์

2
ฉันจะไม่เห็นด้วยกับคำแนะนำนี้เพื่อ "ไม่รำคาญการลบไฟล์เหล่านี้" - เคยเห็นสิ่งนี้แนะนำหลายครั้งล่าสุดโดย"How To Python" ของ Kenneth Reitzเมื่อเร็ว ๆ นี้("bytecode หลอกลวง")
Louis Maddox

38

__pycache__โฟลเดอร์จะถูกสร้างขึ้นเมื่อคุณใช้บรรทัด:

import file_name

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


27

อัปเดตคำตอบจาก 3.7+ เอกสาร:

เพื่อเพิ่มความเร็วในการโหลดโมดูลPython จะแคชรุ่นที่รวบรวมของแต่ละโมดูลใน__pycache__ไดเรกทอรีภายใต้ชื่อ module.version.pycโดยที่รุ่นนั้นเข้ารหัสรูปแบบของไฟล์ที่รวบรวม โดยทั่วไปจะมีหมายเลขเวอร์ชันของ Python ยกตัวอย่างเช่นใน CPython ปล่อย 3.3 รุ่นรวบรวม spam.py __pycache__/spam.cpython-33.pycจะถูกเก็บไว้เป็น ระเบียบการตั้งชื่อนี้อนุญาตให้โมดูลที่คอมไพล์จากรีลีสที่แตกต่างกันและ Python เวอร์ชันต่างกันไปอยู่ร่วมกัน

ที่มา: https://docs.python.org/3/tutorial/modules.html#compiled-python-files

นั่นคือไดเรกทอรีนี้สร้างโดย Python และมีอยู่เพื่อให้โปรแกรมของคุณทำงานได้เร็วขึ้น ไม่ควรมุ่งมั่นที่จะควบคุมแหล่งที่มาและควรอยู่ร่วมกันอย่างสงบสุขกับรหัสที่มาท้องถิ่นของคุณ


__pycache__เป็นไดเรกทอรีที่มีไฟล์แคช bytecode ที่สร้างขึ้นโดยอัตโนมัติโดยไพ ธ อนคือไพ ธ อนที่รวบรวมหรือ.pycไฟล์ คุณอาจสงสัยว่าทำไม Python ซึ่งเป็นภาษา "ตีความ" มีไฟล์ที่คอมไพล์แล้ว คำถาม SO นี้เน้นที่ (และแน่นอนว่าควรอ่านคำตอบนี้ )

หลาม docs มีความลึกมากขึ้นเกี่ยวกับการทำงานและสาเหตุที่มันมีอยู่:

  • มันถูกเพิ่มใน python 3.2เนื่องจากระบบที่มีอยู่ในการดูแลรักษา.pycไฟล์ในไดเรกทอรีเดียวกันทำให้เกิดปัญหาต่าง ๆ เช่นเมื่อโปรแกรมรันด้วย Python interpreters รุ่นต่าง ๆ สำหรับสเปคคุณสมบัติเต็มรูปแบบให้ดูPEP 3174

5

จากโมดูลบทช่วยสอนของไพ ธ อนอย่างเป็นทางการ

เพื่อเพิ่มความเร็วในการโหลดโมดูล Python จะแคชเวอร์ชันที่รวบรวมของแต่ละโมดูลใน__pycache__ไดเรกทอรีภายใต้ชื่อmodule.version.pycโดยที่เวอร์ชันนั้นเข้ารหัสรูปแบบของไฟล์ที่รวบรวม โดยทั่วไปจะมีหมายเลขเวอร์ชันของ Python ยกตัวอย่างเช่นใน CPython ปล่อย 3.6 รุ่นรวบรวม spam.py __pycache__/spam.cpython-36.pycจะถูกเก็บไว้เป็น

จาก Python doc Programming FAQs

เมื่อโมดูลถูกอิมพอร์ตเป็นครั้งแรก (หรือเมื่อไฟล์ต้นฉบับถูกเปลี่ยนตั้งแต่ไฟล์ที่คอมไพล์ปัจจุบันถูกสร้างขึ้น) ไฟล์. pyc ที่มีโค้ดที่คอมไพล์ควรถูกสร้างขึ้นใน__pycache__ไดเรกทอรีย่อยของไดเรกทอรีที่มี.pyไฟล์ .pycไฟล์จะมีชื่อไฟล์ที่เริ่มต้นด้วยชื่อเดียวกับ.pyไฟล์และจบลงด้วย.pycกับองค์ประกอบกลางที่ขึ้นอยู่กับไบนารีหลามโดยเฉพาะอย่างยิ่งที่สร้างมัน


5

การดำเนินการของสคริปต์ python จะทำให้รหัสไบต์ถูกสร้างขึ้นในหน่วยความจำและเก็บไว้จนกว่าโปรแกรมจะปิด ในกรณีที่มีการนำเข้าโมดูลเพื่อให้สามารถนำกลับมาใช้ใหม่ได้เร็วขึ้น Python จะสร้างไฟล์. pyc (PYC คือ 'Python' 'Compiled') โดยที่โค้ดไบต์ของโมดูลที่นำเข้านั้นถูกแคช แนวคิดคือเพิ่มความเร็วในการโหลดโมดูล python โดยหลีกเลี่ยงการคอมไพล์ใหม่ (คอมไพล์ครั้งเดียวรันนโยบายหลายครั้ง) เมื่อนำเข้าอีกครั้ง

ชื่อของไฟล์เหมือนกับชื่อโมดูล ส่วนหลังจากจุดเริ่มต้นบ่งชี้ว่าการใช้งาน Python ที่สร้างแคช (อาจเป็น CPython) ตามด้วยหมายเลขรุ่น


3

python interpreter รวบรวมไฟล์สคริปต์ * .py และบันทึกผลลัพธ์ของการคอมไพล์ไปที่ __pycache__ไดเรกทอรี

เมื่อโครงการดำเนินการอีกครั้งหากล่ามระบุว่าสคริปต์ * .py ยังไม่ได้รับการแก้ไขจะข้ามขั้นตอนการคอมไพล์และเรียกใช้ไฟล์ * .pyc ที่สร้างขึ้นก่อนหน้านี้ที่เก็บไว้ใน __pycache__โฟลเดอร์

เมื่อโครงการมีความซับซ้อนคุณสามารถทำให้เวลาเตรียมการก่อนที่โครงการจะสั้นลง หากโปรแกรมมีขนาดเล็กเกินไปคุณสามารถเพิกเฉยได้โดยใช้python -B abc.pyกับBตัวเลือก


3

Python เวอร์ชัน 2.x จะมี. pycเมื่อล่ามรวบรวมรหัส

Python เวอร์ชัน 3.x จะมี__pycache__เมื่อล่ามรวบรวมรหัส

alok@alok:~$ ls
module.py  module.pyc  __pycache__  test.py
alok@alok:~$

2

ใน 3.2 และหลังจากนั้น Python จะบันทึกไฟล์. pyc ที่คอมไพล์แล้วใน sub-directory ที่มีชื่อ__pycache__อยู่ในไดเรกทอรีที่ไฟล์ต้นฉบับของคุณอยู่กับชื่อไฟล์ที่ระบุเวอร์ชันของ Python ที่สร้างขึ้นมา (เช่น script.cpython-33.pyc)


ฉันจะหลีกเลี่ยงการสร้างโฟลเดอร์ " pycache " ได้อย่างไรและควรมีชื่อ. pyc ทั้งหมดเหมือนกับไฟล์. py
Ashwani

1

เมื่อคุณนำเข้าโมดูล ,

import file_name

Python เก็บ bytecode ที่คอมไพล์ใน__pycache__ไดเรกทอรีเพื่อให้การอิมพอร์ตในอนาคตสามารถใช้โดยตรงแทนที่จะต้องแยกวิเคราะห์และคอมไพล์ซอร์สอีกครั้ง

มันไม่ได้ทำเช่นนั้นเพียงแค่เรียกใช้สคริปต์เท่านั้นเมื่อไฟล์ถูกนำเข้า

(เวอร์ชันก่อนหน้านี้ใช้เพื่อจัดเก็บ bytecode ที่แคชไว้เป็นไฟล์. pyc ที่ทิ้งไดเรกทอรีเดียวกันกับไฟล์. py แต่เริ่มต้นใน Python 3 พวกเขาถูกย้ายไปยังไดเรกทอรีย่อยเพื่อทำให้สิ่งต่าง ๆ เป็นระเบียบ)

PYTHONDONTWRITEBYTECODE ---> หากตั้งค่าเป็นสตริงที่ไม่ว่างเปล่า Python จะไม่พยายามเขียนไฟล์. pyc ในการนำเข้าโมดูลแหล่งที่มา นี่เทียบเท่ากับการระบุอ็อพชัน -B

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