Tôi gặp lỗi trong chương trình được cho là chạy trong một thời gian dài có quá nhiều tệp đang mở. Có cách nào tôi có thể theo dõi các tập tin được mở để tôi có thể in danh sách đó ra thỉnh thoảng và xem vấn đề là ở đâu?kiểm tra xem tệp nào đang mở trong Python
Trả lời
Tôi đã kết thúc gói đối tượng tệp được tích hợp tại điểm nhập của chương trình của tôi. Tôi phát hiện ra rằng tôi đã không đóng cửa sổ ghi chép của mình.
import __builtin__
openfiles = set()
oldfile = __builtin__.file
class newfile(oldfile):
def __init__(self, *args):
self.x = args[0]
print "### OPENING %s ###" % str(self.x)
oldfile.__init__(self, *args)
openfiles.add(self)
def close(self):
print "### CLOSING %s ###" % str(self.x)
oldfile.close(self)
openfiles.remove(self)
oldopen = __builtin__.open
def newopen(*args):
return newfile(*args)
__builtin__.file = newfile
__builtin__.open = newopen
def printOpenFiles():
print "### %d OPEN FILES: [%s]" % (len(openfiles), ", ".join(f.x for f in openfiles))
Tôi đoán rằng bạn đang làm rò rỉ các bộ mô tả tệp. Bạn có thể muốn xem qua mã của bạn để đảm bảo rằng bạn đang đóng tất cả các tệp mà bạn mở.
Tôi nhận ra đó là vấn đề. Tuy nhiên, mã này rất phức tạp và đây là cách dễ dàng để phát hiện ngay lập tức các tệp nào không bị đóng. – Claudiu
Trên Windows, bạn có thể sử dụng Process Explorer để hiển thị tất cả các tệp xử lý thuộc sở hữu của một quy trình.
Trên Linux, bạn có thể sử dụng lsof
để hiển thị tất cả các tệp được mở bởi một quy trình.
Có python một số chức năng nội bộ cho lsof, hoặc tôi thực sự phải gọi linux lsof? – sumid
Trên Linux, bạn có thể xem nội dung của /proc/self/fd
:
$ ls -l /proc/self/fd/
total 0
lrwx------ 1 foo users 64 Jan 7 15:15 0 -> /dev/pts/3
lrwx------ 1 foo users 64 Jan 7 15:15 1 -> /dev/pts/3
lrwx------ 1 foo users 64 Jan 7 15:15 2 -> /dev/pts/3
lr-x------ 1 foo users 64 Jan 7 15:15 3 -> /proc/9527/fd
Đây có phải là chỉ cho CPython hoặc tất cả các triển khai? Tôi nhớ, tôi nghĩ rằng, các tập tin mở trong ipython được liệt kê trong '/ proc/ipython_pid/fd /'. Ngoài ra, trong danh sách ở trên, làm thế nào để bạn biết những tập tin bạn đã mở và đó là những tập tin mà Python đã mở (và bạn không nên đóng)? – Chris
Điều này dành cho các hệ thống Linux cung cấp hệ thống tệp '/ proc'. Nó độc lập với ngôn ngữ; bất kỳ chương trình nào trong bất kỳ ngôn ngữ nào có thể truy cập "tệp" trong '/ proc' đều có thể lấy thông tin này. Tôi đã không rối tung với ipython, nhưng ý tưởng cơ bản sẽ là ghi lại nội dung của '/ proc/self/fd' sau khi khởi tạo và sau đó so sánh nội dung sau đó trong quá trình chạy để tìm các thay đổi. –
Mặc dù các giải pháp trên bọc mở ra rất hữu ích cho mã riêng của một người, tôi đã gỡ khách hàng của tôi đến một thư viện của bên thứ ba bao gồm một số mã mở rộng c, vì vậy tôi cần một cách trực tiếp hơn. Công việc thường xuyên sau đây hoạt động dưới darwin, và (tôi hy vọng) các môi trường giống như Unix khác:
def get_open_fds():
'''
return the number of open file descriptors for current process
.. warning: will only work on UNIX-like os-es.
'''
import subprocess
import os
pid = os.getpid()
procs = subprocess.check_output(
[ "lsof", '-w', '-Ff', "-p", str(pid) ])
nprocs = len(
filter(
lambda s: s and s[ 0 ] == 'f' and s[1: ].isdigit(),
procs.split('\n'))
)
return nprocs
Nếu ai đó có thể mở rộng để di động đến cửa sổ, tôi sẽ biết ơn.
được giảm giá cho kiểu xấu. pep8! – Newb
Có một số hạn chế đối với phản hồi được chấp nhận, ở chỗ nó dường như không tính các đường ống. Tôi đã có một kịch bản python đã mở nhiều quy trình phụ và không đóng đúng các đầu vào, đầu ra và đường ống lỗi chuẩn được sử dụng để liên lạc. Nếu tôi sử dụng phản hồi được chấp nhận, nó sẽ không tính các ống mở này là các tệp mở, nhưng (ít nhất là trong Linux) chúng là các tệp mở và được tính vào giới hạn tệp mở. Giải pháp lsof -p
được đề xuất bởi sumid và shunc hoạt động trong tình huống này, bởi vì nó cũng cho bạn thấy các đường ống mở.
Nhận danh sách tất cả các tệp đang mở. handle.exe
là một phần của Sysinternals Suite của Microsoft. Một thay thế là mô-đun Python psutil, nhưng tôi tìm thấy 'xử lý' sẽ in ra nhiều tập tin được sử dụng.
Đây là những gì tôi đã thực hiện. Cảnh báo mã Kludgy.
#!/bin/python3
# coding: utf-8
"""Build set of files that are in-use by processes.
Requires 'handle.exe' from Microsoft SysInternals Suite.
This seems to give a more complete list than using the psutil module.
"""
from collections import OrderedDict
import os
import re
import subprocess
# Path to handle executable
handle = "E:/Installers and ZIPs/Utility/Sysinternalssuite/handle.exe"
# Get output string from 'handle'
handle_str = subprocess.check_output([handle]).decode(encoding='ASCII')
""" Build list of lists.
1. Split string output, using '-' * 78 as section breaks.
2. Ignore first section, because it is executable version info.
3. Turn list of strings into a list of lists, ignoring first item (it's empty).
"""
work_list = [x.splitlines()[1:] for x in handle_str.split(sep='-' * 78)[1:]]
""" Build OrderedDict of pid information.
pid_dict['pid_num'] = ['pid_name','open_file_1','open_file_2', ...]
"""
pid_dict = OrderedDict()
re1 = re.compile("(.*?\.exe) pid: ([0-9]+)") # pid name, pid number
re2 = re.compile(".*File.*\s\s\s(.*)") # File name
for x_list in work_list:
key = ''
file_values = []
m1 = re1.match(x_list[0])
if m1:
key = m1.group(2)
# file_values.append(m1.group(1)) # pid name first item in list
for y_strings in x_list:
m2 = re2.match(y_strings)
if m2:
file_values.append(m2.group(1))
pid_dict[key] = file_values
# Make a set of all the open files
values = []
for v in pid_dict.values():
values.extend(v)
files_open = sorted(set(values))
txt_file = os.path.join(os.getenv('TEMP'), 'lsof_handle_files')
with open(txt_file, 'w') as fd:
for a in sorted(files_open):
fd.write(a + '\n')
subprocess.call(['notepad', txt_file])
os.remove(txt_file)
Như đã nói ở trên, bạn có thể liệt kê FDS trên Linux trong /proc/self/fd, đây là một phương pháp đơn giản để liệt kê chúng theo chương trình:
import os
import sys
import errno
def list_fds():
"""List process currently open FDs and their target """
if sys.platform != 'linux2':
raise NotImplementedError('Unsupported platform: %s' % sys.platform)
ret = {}
base = '/proc/self/fd'
for num in os.listdir(base):
path = None
try:
path = os.readlink(os.path.join(base, num))
except OSError as err:
# Last FD is always the "listdir" one (which may be closed)
if err.errno != errno.ENOENT:
raise
ret[int(num)] = path
return ret
Để liệt kê tất cả các file mở trong một cách đa nền tảng, tôi sẽ giới thiệu psutil.
#!/usr/bin/env python
import psutil
for proc in psutil.process_iter():
print proc.open_files()
Câu hỏi ban đầu ngụ ý hạn chế hoạt động đối với quy trình hiện đang chạy, có thể truy cập thông qua lớp Process của psutil.
proc = psutil.Process()
print proc.open_files()
Cuối cùng, bạn sẽ muốn chạy mã bằng tài khoản thích hợp để truy cập thông tin này hoặc bạn có thể thấy lỗi AccessDenied.
Điều này dường như chỉ hoạt động đối với các tệp dựa trên đĩa, không phải ổ cắm, fifos, v.v. – NeilenMarais
@NeilenMarais: nó hoạt động với các ổ cắm, xem ví dụ tại https://pypi.python.org/pypi/psutil – LetMeSOThat4U
Các phiên bản mới của psutil sử dụng tên 'proc.get_open_files()' – gerardw
Bạn có thể sử dụng tập lệnh sau. Nó được xây dựng trên answer của Claudiu. Nó đề cập đến một số vấn đề và bổ sung thêm các tính năng:
- In một chồng dấu vết của tập tin đã mở
- Vẽ và trang trí lối ra chương trình
- hỗ trợ lập luận theo từ khóa
Dưới đây là các mã và một liên kết đến gist, có thể cập nhật hơn.
"""
Collect stacktraces of where files are opened, and prints them out before the
program exits.
Example
========
monitor.py
----------
from filemonitor import FileMonitor
FileMonitor().patch()
f = open('/bin/ls')
# end of monitor.py
$ python monitor.py
----------------------------------------------------------------------------
path = /bin/ls
> File "monitor.py", line 3, in <module>
> f = open('/bin/ls')
----------------------------------------------------------------------------
Solution modified from:
https://stackoverflow.com/questions/2023608/check-what-files-are-open-in-python
"""
from __future__ import print_function
import __builtin__
import traceback
import atexit
import textwrap
class FileMonitor(object):
def __init__(self, print_only_open=True):
self.openfiles = []
self.oldfile = __builtin__.file
self.oldopen = __builtin__.open
self.do_print_only_open = print_only_open
self.in_use = False
class File(self.oldfile):
def __init__(this, *args, **kwargs):
path = args[0]
self.oldfile.__init__(this, *args, **kwargs)
if self.in_use:
return
self.in_use = True
self.openfiles.append((this, path, this._stack_trace()))
self.in_use = False
def close(this):
self.oldfile.close(this)
def _stack_trace(this):
try:
raise RuntimeError()
except RuntimeError as e:
stack = traceback.extract_stack()[:-2]
return traceback.format_list(stack)
self.File = File
def patch(self):
__builtin__.file = self.File
__builtin__.open = self.File
atexit.register(self.exit_handler)
def unpatch(self):
__builtin__.file = self.oldfile
__builtin__.open = self.oldopen
def exit_handler(self):
indent = ' > '
terminal_width = 80
for file, path, trace in self.openfiles:
if file.closed and self.do_print_only_open:
continue
print("-" * terminal_width)
print(" {} = {}".format('path', path))
lines = ''.join(trace).splitlines()
_updated_lines = []
for l in lines:
ul = textwrap.fill(l,
initial_indent=indent,
subsequent_indent=indent,
width=terminal_width)
_updated_lines.append(ul)
lines = _updated_lines
print('\n'.join(lines))
print("-" * terminal_width)
print()
- 1. Kiểm tra xem tệp có đang mở
- 2. Python/win32com - Kiểm tra xem Chương trình có đang mở
- 3. Kiểm tra xem cổng có đang mở trong ANT
- 4. Kiểm tra xem tệp mở đã bị xóa sau khi mở trong python
- 5. Kiểm tra xem kết nối ADODB có đang mở không
- 6. Ruby - Kiểm tra xem cổng có đang mở
- 7. Ràng buộc Python AppIndicator -> howto kiểm tra xem menu có đang mở không?
- 8. Kiểm tra xem Chronometer có đang chạy
- 9. Kiểm tra xem tệp có đang được sử dụng hay ứng dụng nào không?
- 10. Kiểm tra xem ổ cắm có đang nghe trong C
- 11. Python - Kiểm tra xem tệp có trống hay không
- 12. Kiểm tra tệp được mở ở Delphi
- 13. Kiểm tra xem tệp có định dạng CSV với Python
- 14. Kiểm tra xem Tệp PDF có hợp lệ không (Python)
- 15. Cách kiểm tra xem các yêu cầu HTTP có đang mở trong trình duyệt không?
- 16. Kiểm tra xem ứng dụng có đang mở trong sự kiện GCM onMessage không?
- 17. Cách lấy dòng tệp đang mở trong python?
- 18. Kiểm tra xem có cảnh báo nào đang tồn tại khi sử dụng selen với python
- 19. Làm thế nào để kiểm tra xem tôi đang chạy trên Windows bằng Python?
- 20. Delphi: Kiểm tra xem tệp có đang được sử dụng hay không
- 21. Kiểm tra xem tệp có mở hay không (không được sử dụng bởi quy trình khác) trong Python
- 22. TFS 2010: Kiểm tra tệp mở
- 23. Kiểm tra xem quy trình có đang chạy bằng Python (trong Linux/Unix)
- 24. Kiểm tra xem tệp có tồn tại trong Yii
- 25. Cách kiểm tra xem phần tử chọn vẫn còn "mở"/đang hoạt động với jquery
- 26. kiểm tra xem ổ cắm máy chủ có đang mở ở phía bên kia không
- 27. Phát hiện xem tệp có đang mở trong một tệp theo lô hay không
- 28. Bảng điều khiển jQuery Mobile - kiểm tra xem nó có đang mở không.
- 29. Kiểm tra xem tệp có phải là một đường ống có tên (nămo) trong python không?
- 30. Kiểm tra xem Chú giải Công cụ UI của jQuery có đang mở không
Làm việc như một sự quyến rũ đối với tôi, cảm ơn bạn đã chia sẻ! –
@Claudiu - bạn có thể vui lòng cách đóng tất cả các tệp đang mở - def closeall (tự): in "### CLOSING Tất cả các tệp ###" \t oldfile.close (self, (fx for f in openfiles)) openfiles.remove (tự, (fx cho f trong openfiles)) Sẽ hoạt động hoàn hảo? – Prakash
Để không kéo dài tuổi thọ của các đối tượng tệp (và do đó ngăn tự động đóng đối tượng được tính trong tham chiếu trong cpython), giá trị IMO sử dụng 'weakref.WeakSet' thay vì' set' đơn giản cho 'openfiles'. – coldfix