Làm thế nào để tránh các tập tin .pyc?


268

Tôi có thể chạy trình thông dịch python mà không tạo các tệp .pyc đã biên dịch không?

Câu trả lời:


288

Từ "Có gì mới trong Python 2.6 - Thay đổi trình thông dịch" :

Bây giờ Python có thể được ngăn không cho ghi các tệp .pyc hoặc .pyo bằng cách cung cấp khóa -B cho trình thông dịch Python hoặc bằng cách đặt biến môi trường PYTHONDONTWRITEBYTECODE trước khi chạy trình thông dịch. Cài đặt này có sẵn cho các chương trình Python dưới dạng sys.dont_write_bytecodebiến và mã Python có thể thay đổi giá trị để sửa đổi hành vi của trình thông dịch.

Cập nhật 2010-11-27: Python 3.2 giải quyết vấn đề làm lộn xộn các thư mục nguồn với .pyccác tệp bằng cách giới thiệu một __pycache__thư mục con đặc biệt , xem Có gì mới trong Python 3.2 - Thư mục kho lưu trữ PYC .


1
Ít nhất trên OS X 10.8 chạy Python 2.7, biến môi trường không có hiệu lực.
sorin

5
Nếu bạn đang nhúng trình thông dịch (trong chương trình C ++), hãy sử dụng "Py_DontWriteBytecodeFlag = 1;" trong mã nguồn của bạn. Đó là một int toàn cầu được tuyên bố trong pydebug.h.
JimB

1
Biến môi trường hoạt động tốt với tôi trong 2.7, không biết người khác đang gặp vấn đề gì. Cảm ơn!
Thomas

8
Làm việc cho tôi cũng vậy trên OSX (10.8 & 10.10); @sorin bạn đã xuất biến đúng chưa? export PYTHONDONTWRITEBYTECODE=1
nevelis

1
Bạn có biết làm thế nào để làm điều tương tự với pytest?

110
import sys

sys.dont_write_bytecode = True

25
Tôi đã thử điều này và, nó hoạt động cho các mô-đun nhập khẩu. Cụ thể, một khi biến này được đặt, mọi thứ được nhập sau đó sẽ không tạo tệp pyc. Điều này thật thú vị. Cảm ơn.

Thay vì thêm phần này vào Mô-đun gốc, hãy thử thêm phần này vào Tập lệnh được tham chiếu. Điều này làm việc mát mẻ. Cảm ơn @te wilson
Sathy

4
Thêm phần này vào của bạn site-packages/usercustomize.pyđể áp dụng điều này cho tất cả các tập lệnh của bạn. Đối với tôi, thư mục này là $HOME/.local/lib/python2.6/site-pacakges/usercustomize.py. Cf. docs.python.org/2/tutorial/ trộm
RobM

3
Các gói trang web của tôi được đặt tại: /usr/local/lib/python2.7/site-packages và tôi phải tạo usercustomize.py
anon58192932

3
Hoặc trong một dòng:import sys; sys.dont_write_bytecode = True
ET-CS

23

Thực sự có một cách để làm điều đó trong Python 2.3+, nhưng đó là một chút bí truyền. Tôi không biết nếu bạn nhận ra điều này, nhưng bạn có thể làm như sau:

$ unzip -l /tmp/example.zip
 Archive:  /tmp/example.zip
   Length     Date   Time    Name
 --------    ----   ----    ----
     8467  11-26-02 22:30   jwzthreading.py
 --------                   -------
     8467                   1 file
$ ./python
Python 2.3 (#1, Aug 1 2003, 19:54:32) 
>>> import sys
>>> sys.path.insert(0, '/tmp/example.zip')  # Add .zip file to front of path
>>> import jwzthreading
>>> jwzthreading.__file__
'/tmp/example.zip/jwzthreading.py'

Theo thư viện zipimport :

Bất kỳ tệp nào cũng có thể có trong kho lưu trữ ZIP, nhưng chỉ các tệp .py và .py [co] có sẵn để nhập. Nhập ZIP của các mô-đun động (.pyd, .so) không được phép. Lưu ý rằng nếu tệp lưu trữ chỉ chứa tệp .py, Python sẽ không cố gắng sửa đổi tệp lưu trữ bằng cách thêm tệp .pyc hoặc .pyo tương ứng, nghĩa là nếu tệp lưu trữ ZIP không chứa tệp .pyc, việc nhập có thể khá chậm.

Vì vậy, tất cả những gì bạn phải làm là nén các tệp lên, thêm zipfile vào sys.path của bạn và sau đó nhập chúng.

Nếu bạn đang xây dựng điều này cho UNIX, bạn cũng có thể xem xét việc đóng gói tập lệnh của mình bằng công thức này: unix zip có thể thực thi được , nhưng lưu ý rằng bạn có thể phải điều chỉnh điều này nếu bạn dự định sử dụng stdin hoặc đọc bất cứ thứ gì từ sys.args (nó có thể thực hiện mà không gặp quá nhiều rắc rối).

Theo kinh nghiệm của tôi, hiệu suất không bị ảnh hưởng quá nhiều vì điều này, nhưng bạn nên suy nghĩ kỹ trước khi nhập bất kỳ mô-đun rất lớn nào theo cách này.


11

Trong 2.5, không có cách nào để ngăn chặn nó, ngoại trừ các biện pháp như không cho phép người dùng ghi quyền truy cập vào thư mục.

Tuy nhiên, trong python 2.6 và 3.0, có thể có một cài đặt trong mô-đun sys có tên "dont_write_bytecode" có thể được đặt để triệt tiêu điều này. Điều này cũng có thể được đặt bằng cách chuyển tùy chọn "-B" hoặc đặt biến môi trường "PYTHONDONTWRITEBYTECODE"


7

Bạn có thể thiết lập sys.dont_write_bytecode = Truetrong nguồn của mình, nhưng đó sẽ phải nằm trong tệp python đầu tiên được tải. Nếu bạn thực hiện python somefile.pythì bạn sẽ không nhận được somefile.pyc.

Khi bạn cài đặt một tiện ích bằng cách sử dụng setup.pyentry_points=bạn sẽ thiết lập sys.dont_write_bytecodetrong tập lệnh khởi động. Vì vậy, bạn không thể dựa vào tập lệnh khởi động "mặc định" được tạo bởi setuptools.

Nếu bạn khởi động Python với tệp python làm đối số, bạn có thể chỉ định -B:

python -B somefile.py

somefile.pycdù sao cũng sẽ không được tạo, nhưng cũng không có .pyctệp nào cho các tệp khác được nhập.

Nếu bạn có một số tiện ích myutilvà bạn không thể thay đổi điều đó, nó sẽ không chuyển -B cho trình thông dịch python. Chỉ cần bắt đầu bằng cách đặt biến môi trường PYTHONDONTWRITEBYTECODE:

PYTHONDONTWRITEBYTECODE=x myutil

4

Tôi có một số trường hợp thử nghiệm trong bộ thử nghiệm và trước khi tôi chạy bộ thử nghiệm trong Mac Terminal như thế này:

python LoginSuite.py

Chạy lệnh theo cách này thư mục của tôi đã được điền với các tệp .pyc. Tôi đã thử phương pháp đã nêu dưới đây và nó đã giải quyết được vấn đề:

python -B LoginSuite.py

Phương pháp này hoạt động nếu bạn đang nhập các trường hợp kiểm thử vào bộ kiểm tra và chạy bộ trên dòng lệnh.


4

Bắt đầu với Python 3.8, bạn có thể sử dụng biến môi trường PYTHONPYCACHEPREFIXđể xác định thư mục bộ đệm cho Python.

Từ các tài liệu Python:

Nếu điều này được đặt, Python sẽ ghi các tệp .pyc vào cây thư mục nhân bản tại đường dẫn này, thay vì trong pycache thư mục trong cây nguồn. Điều này tương đương với việc chỉ định tùy chọn -X pycache_prefix = PATH.

Thí dụ

Nếu bạn thêm dòng sau ./profilevào Linux của bạn :

export PYTHONPYCACHEPREFIX="$HOME/.cache/cpython/"

Python sẽ không tạo các __pycache__thư mục gây phiền nhiễu trong thư mục dự án của bạn, thay vào đó, nó sẽ đặt tất cả chúng vào~/.cache/cpython/


2

Bạn có thể làm cho các thư mục mà các mô-đun của bạn tồn tại ở chế độ chỉ đọc cho người dùng mà trình thông dịch Python đang chạy.

Tôi không nghĩ có một lựa chọn thanh lịch hơn. PEP 304 dường như là một nỗ lực để giới thiệu một tùy chọn đơn giản cho việc này, nhưng dường như nó đã bị bỏ rơi.

Tôi tưởng tượng có thể có một số vấn đề khác mà bạn đang cố gắng giải quyết, trong đó việc vô hiệu hóa .py [co] có vẻ là một cách giải quyết, nhưng có lẽ sẽ tốt hơn nếu tấn công bất cứ vấn đề ban đầu nào thay vào đó.


2

Giải pháp cho ipython 6.2.1 using python 3.5.2(Đã thử nghiệm trên Ubuntu 16.04 và Windows 10):

Ipythonkhông tôn trọng %env PYTHONDONTWRITEBYTECODE =1nếu được đặt trong trình ipythonthông dịch hoặc trong khi khởi động ~/.ipython/profile-default/startup/00-startup.ipy. Thay vì sử dụng những điều sau đây trong~.ipython/profile-default/startup/00-startup.py

import sys
sys.dont_write_bytecode=True

0

Theo tôi biết python sẽ biên dịch tất cả các mô-đun bạn "nhập". Tuy nhiên, python sẽ KHÔNG biên dịch tập lệnh python bằng cách sử dụng: "python script.py" (tuy nhiên, nó sẽ biên dịch bất kỳ mô-đun nào mà tập lệnh nhập).

Các câu hỏi thực sự là tại sao bạn không muốn python biên dịch các mô-đun? Bạn có thể có thể tự động hóa một cách để làm sạch những thứ này nếu chúng cản trở.


Tôi đã tìm thấy thường xuyên rằng có .pyccác tập tin mã byte cũ . Vì một số lý do, khi tôi thay đổi lớp / mô-đun, .pyctệp không được cập nhật. Vì vậy, khi tôi nhập nó sau khi thay đổi.py tệp, nó vẫn sẽ sử dụng .pyctệp, dẫn đến lỗi
alpha_989
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.