Einführung
Dieses umfassende Tutorial führt Sie durch die Verwendung der ctypes-Bibliothek von Python zur Interaktion mit der Windows API. Sie lernen, wie Sie auf Windows-Systemfunktionen zugreifen, Prozesse verwalten und Windows-spezifische Funktionen direkt von Python aus nutzen können. Am Ende dieses Labors werden Sie verstehen, wie Sie Anwendungen erstellen, die sich nahtlos in das Windows-Betriebssystem integrieren und leistungsstarke Operationen auf Systemebene durchführen können.
Grundlagen der Python-Bibliothek ctypes
In diesem Schritt werden wir die Grundlagen der ctypes-Bibliothek von Python untersuchen, die als Grundlage für die Interaktion mit der Windows API dient. Die ctypes-Bibliothek fungiert als Brücke zwischen Python und nativen C-Bibliotheken und ermöglicht es uns, Funktionen direkt aus DLLs (Dynamic Link Libraries) aufzurufen.
Was ist ctypes?
ctypes ist eine Foreign Function Library für Python, die C-kompatible Datentypen bereitstellt und das Aufrufen von Funktionen in DLLs oder Shared Libraries ermöglicht. Sie ist besonders nützlich für:
- Zugriff auf Systemfunktionen auf niedriger Ebene
- Interaktion mit Hardware
- Aufrufen von Funktionen aus plattformspezifischen Bibliotheken
Installieren der erforderlichen Pakete
Bevor wir mit dem Schreiben von Code beginnen, installieren wir die notwendigen Pakete. Öffnen Sie ein Terminal in der WebIDE und führen Sie aus:
pip install pywin32-ctypes
Dadurch wird eine kompatible Bibliothek installiert, die mit unserer Umgebung funktioniert.
Grundlegende Verwendung von ctypes
Erstellen wir ein einfaches Python-Skript, um zu verstehen, wie ctypes funktioniert. Erstellen Sie in der WebIDE eine neue Datei namens ctypes_basics.py im Verzeichnis /home/labex/project mit folgendem Inhalt:
import ctypes
## Load a standard C library
libc = ctypes.CDLL('libc.so.6')
## Call a simple C function
print("Random number from C library:", libc.rand())
## Find out the size of int type on this machine
print("Size of int:", ctypes.sizeof(ctypes.c_int), "bytes")
## Create and use a C-compatible string
message = ctypes.create_string_buffer(b"Hello from ctypes!")
print("C-compatible string:", message.value.decode())
print("String buffer size:", ctypes.sizeof(message), "bytes")
Führen Sie das Skript mit folgendem Befehl aus:
python3 ctypes_basics.py
Sie sollten eine Ausgabe ähnlich dieser sehen:
Random number from C library: 1804289383
Size of int: 4 bytes
C-compatible string: Hello from ctypes!
String buffer size: 19 bytes
Verstehen von C-Datentypen in Python
ctypes stellt Python-kompatible Wrapper für C-Datentypen bereit. Hier ist eine Referenztabelle der gängigen C-Datentypen und ihrer ctypes-Äquivalente:
| C-Typ | ctypes-Typ | Python-Typ |
|---|---|---|
| char | c_char | 1-Zeichen-Bytes-Objekt |
| int | c_int | int |
| unsigned int | c_uint | int |
| long | c_long | int |
| void * | c_void_p | int oder None |
| char * | c_char_p | bytes oder None |
| wchar_t * | c_wchar_p | str oder None |
Lassen Sie uns diese Datentypen mit einem weiteren Beispiel untersuchen. Erstellen Sie eine Datei namens ctypes_types.py:
import ctypes
## Integer types
i = ctypes.c_int(42)
ui = ctypes.c_uint(123)
print(f"Integer: {i.value}, Unsigned Integer: {ui.value}")
## Floating point types
f = ctypes.c_float(3.14)
d = ctypes.c_double(2.71828)
print(f"Float: {f.value}, Double: {d.value}")
## Character and string types
c = ctypes.c_char(b'A')
s = ctypes.c_char_p(b"Hello, World!")
print(f"Character: {c.value.decode()}, String: {s.value.decode()}")
## Create an array of integers
int_array = (ctypes.c_int * 5)(1, 2, 3, 4, 5)
print("Array elements:", [int_array[i] for i in range(5)])
Führen Sie das Skript aus:
python3 ctypes_types.py
Erwartete Ausgabe:
Integer: 42, Unsigned Integer: 123
Float: 3.140000104904175, Double: 2.71828
Character: A, String: Hello, World!
Array elements: [1, 2, 3, 4, 5]
Dieses grundlegende Verständnis von ctypes wird uns helfen, wenn wir uns der Interaktion mit komplexeren Systembibliotheken und insbesondere der Windows API zuwenden.
Zugriff auf Systembibliotheken mit ctypes
In diesem Schritt lernen wir, wie man mit ctypes auf Systembibliotheken zugreift und deren Funktionen aufruft. Da wir in einer Linux-Umgebung arbeiten, konzentrieren wir uns auf Linux-Systembibliotheken, während wir die Prinzipien erklären, die auch für den Zugriff auf die Windows API gelten.
Laden dynamischer Bibliotheken
In Python können wir dynamische Bibliotheken mit verschiedenen Methoden laden, die von ctypes bereitgestellt werden:
CDLL- zum Laden von Standard-C-BibliothekenWinDLL- zum Laden von Windows DLLs (wenn unter Windows)OleDLL- zum Laden von COM-Bibliotheken (wenn unter Windows)
Erstellen wir eine Datei namens system_info.py, um Systeminformationen mithilfe von Standardbibliotheken zu untersuchen:
import ctypes
import os
import platform
print(f"Python Platform: {platform.platform()}")
print(f"System: {platform.system()}")
print(f"Machine: {platform.machine()}")
print(f"Processor: {platform.processor()}")
## Load the C standard library
libc = ctypes.CDLL('libc.so.6')
## Get system information
print("\n--- System Information ---")
## Get hostname
hostname_buffer = ctypes.create_string_buffer(1024)
if libc.gethostname(hostname_buffer, ctypes.sizeof(hostname_buffer)) == 0:
print(f"Hostname: {hostname_buffer.value.decode()}")
else:
print("Failed to get hostname")
## Get user information
uid = os.getuid()
pwd = libc.getpwuid(uid)
if pwd:
print(f"Current user ID: {uid}")
else:
print(f"Current user ID: {uid} (failed to get user info)")
## Memory page size
page_size = libc.getpagesize()
print(f"Memory page size: {page_size} bytes")
## Get system uptime (if available)
try:
class timespec(ctypes.Structure):
_fields_ = [
('tv_sec', ctypes.c_long),
('tv_nsec', ctypes.c_long)
]
time_buf = timespec()
CLOCK_BOOTTIME = 7 ## Linux specific
if hasattr(libc, 'clock_gettime') and libc.clock_gettime(CLOCK_BOOTTIME, ctypes.byref(time_buf)) == 0:
uptime_seconds = time_buf.tv_sec
days, remainder = divmod(uptime_seconds, 86400)
hours, remainder = divmod(remainder, 3600)
minutes, seconds = divmod(remainder, 60)
print(f"System uptime: {days} days, {hours} hours, {minutes} minutes, {seconds} seconds")
else:
print("Could not get system uptime")
except Exception as e:
print(f"Error getting uptime: {e}")
Führen Sie das Skript aus:
python3 system_info.py
Sie sollten detaillierte Informationen über Ihr System sehen, ähnlich wie diese:
Python Platform: Linux-5.15.0-1031-aws-x86_64-with-glibc2.35
System: Linux
Machine: x86_64
Processor: x86_64
--- System Information ---
Hostname: labex-container
Current user ID: 1000
Memory page size: 4096 bytes
System uptime: 0 days, 1 hours, 23 minutes, 45 seconds
Erstellen eines Prozessmonitors
Erstellen wir nun eine praktischere Anwendung: einen einfachen Prozessmonitor, der laufende Prozesse auflistet. Erstellen Sie eine Datei namens process_monitor.py:
import ctypes
import os
import time
from datetime import datetime
def list_processes():
"""List all running processes using /proc filesystem"""
processes = []
## On Linux, process information is available in the /proc filesystem
for pid in os.listdir('/proc'):
if pid.isdigit():
try:
## Read process name from /proc/[pid]/comm
with open(f'/proc/{pid}/comm', 'r') as f:
name = f.read().strip()
## Get process status
with open(f'/proc/{pid}/status', 'r') as f:
status_lines = f.readlines()
status = {}
for line in status_lines:
if ':' in line:
key, value = line.split(':', 1)
status[key.strip()] = value.strip()
## Get memory usage (VmRSS is physical memory used)
memory_kb = int(status.get('VmRSS', '0 kB').split()[0]) if 'VmRSS' in status else 0
processes.append({
'pid': int(pid),
'name': name,
'state': status.get('State', 'Unknown'),
'memory_kb': memory_kb
})
except (IOError, FileNotFoundError, ProcessLookupError):
## Process might have terminated while we were reading
continue
return processes
def display_processes(processes, top_n=10):
"""Display processes sorted by memory usage"""
## Sort processes by memory usage (highest first)
sorted_processes = sorted(processes, key=lambda p: p['memory_kb'], reverse=True)
## Display only top N processes
print(f"\nTop {top_n} processes by memory usage at {datetime.now().strftime('%H:%M:%S')}:")
print(f"{'PID':<7} {'NAME':<20} {'STATE':<10} {'MEMORY (KB)':<12}")
print("-" * 50)
for proc in sorted_processes[:top_n]:
print(f"{proc['pid']:<7} {proc['name'][:19]:<20} {proc['state']:<10} {proc['memory_kb']:<12}")
## Monitor processes continuously
print("Simple Process Monitor")
print("Press Ctrl+C to exit")
try:
while True:
processes = list_processes()
display_processes(processes)
time.sleep(3) ## Update every 3 seconds
except KeyboardInterrupt:
print("\nProcess monitoring stopped")
Führen Sie den Prozessmonitor aus:
python3 process_monitor.py
Sie sollten eine Ausgabe ähnlich dieser sehen, die sich alle 3 Sekunden aktualisiert:
Simple Process Monitor
Press Ctrl+C to exit
Top 10 processes by memory usage at 14:30:25:
PID NAME STATE MEMORY (KB)
-------------------------------------------------------
1234 python3 S (sleeping) 56789
2345 node S (sleeping) 34567
3456 code S (sleeping) 23456
...
Lassen Sie den Prozessmonitor etwa 10 Sekunden lang laufen und drücken Sie dann Ctrl+C, um ihn zu stoppen.
In diesen Beispielen haben wir gelernt, wie man:
- Systembibliotheken mit
ctypeslädt und verwendet - Auf Systeminformationen zugreift
- Ein praktisches Werkzeug zur Prozessüberwachung erstellt
Diese Prinzipien sind dieselben, die Sie verwenden würden, um über ctypes mit der Windows API zu interagieren, nur mit unterschiedlichen Bibliotheksnamen und Funktionsaufrufen.
Erstellen und Verwenden von C-Structs mit ctypes
In diesem Schritt lernen wir, wie man C-Strukturen in Python definiert und verwendet. Strukturen sind unerlässlich, wenn man mit System-APIs arbeitet, da sie häufig zum Austausch von Daten zwischen Python und Systembibliotheken verwendet werden.
Verstehen von C-Strukturen in Python
C-Strukturen können in Python mithilfe der Klasse ctypes.Structure dargestellt werden. Dies ermöglicht es uns, komplexe Datenstrukturen zu erstellen, die dem Speicherlayout entsprechen, das von C-Funktionen erwartet wird.
Erstellen wir eine Datei namens struct_example.py, um zu untersuchen, wie man mit Strukturen arbeitet:
import ctypes
## Define a simple C structure
class Point(ctypes.Structure):
_fields_ = [
("x", ctypes.c_int),
("y", ctypes.c_int)
]
## Create an instance of the Point structure
p = Point(10, 20)
print(f"Point coordinates: ({p.x}, {p.y})")
## Modify structure fields
p.x = 100
p.y = 200
print(f"Updated coordinates: ({p.x}, {p.y})")
## Create a Point from a dictionary
values = {"x": 30, "y": 40}
p2 = Point(**values)
print(f"Point from dictionary: ({p2.x}, {p2.y})")
## Get the raw memory view (pointer) of the structure
p_ptr = ctypes.pointer(p)
print(f"Memory address of p: {ctypes.addressof(p)}")
print(f"Access via pointer: ({p_ptr.contents.x}, {p_ptr.contents.y})")
## Define a nested structure
class Rectangle(ctypes.Structure):
_fields_ = [
("top_left", Point),
("bottom_right", Point),
("color", ctypes.c_int)
]
## Create a rectangle with two points
rect = Rectangle(Point(0, 0), Point(100, 100), 0xFF0000)
print(f"Rectangle: Top-Left: ({rect.top_left.x}, {rect.top_left.y}), "
f"Bottom-Right: ({rect.bottom_right.x}, {rect.bottom_right.y}), "
f"Color: {hex(rect.color)}")
## Calculate the area (demonstrating structure manipulation)
width = rect.bottom_right.x - rect.top_left.x
height = rect.bottom_right.y - rect.top_left.y
print(f"Rectangle area: {width * height}")
Führen Sie das Skript aus:
python3 struct_example.py
Sie sollten eine Ausgabe ähnlich dieser sehen:
Point coordinates: (10, 20)
Updated coordinates: (100, 200)
Point from dictionary: (30, 40)
Memory address of p: 140737345462208
Access via pointer: (100, 200)
Rectangle: Top-Left: (0, 0), Bottom-Right: (100, 100), Color: 0xff0000
Rectangle area: 10000
Erstellen eines Systemzeit-Dienstprogramms
Erstellen wir nun eine praktische Anwendung, die C-Strukturen verwendet, um mit den Systemzeitfunktionen zu interagieren. Erstellen Sie eine Datei namens time_utility.py:
import ctypes
import time
from datetime import datetime
## Define the timespec structure (used in Linux for high-resolution time)
class timespec(ctypes.Structure):
_fields_ = [
("tv_sec", ctypes.c_long),
("tv_nsec", ctypes.c_long)
]
## Define the tm structure (used for calendar time representation)
class tm(ctypes.Structure):
_fields_ = [
("tm_sec", ctypes.c_int), ## seconds (0 - 60)
("tm_min", ctypes.c_int), ## minutes (0 - 59)
("tm_hour", ctypes.c_int), ## hours (0 - 23)
("tm_mday", ctypes.c_int), ## day of month (1 - 31)
("tm_mon", ctypes.c_int), ## month of year (0 - 11)
("tm_year", ctypes.c_int), ## year - 1900
("tm_wday", ctypes.c_int), ## day of week (0 - 6, Sunday = 0)
("tm_yday", ctypes.c_int), ## day of year (0 - 365)
("tm_isdst", ctypes.c_int) ## is daylight saving time in effect
]
## Load the C library
libc = ctypes.CDLL("libc.so.6")
def get_system_time():
"""Get the current system time using C functions"""
## Get current time as seconds since epoch
time_t_ptr = ctypes.pointer(ctypes.c_long())
libc.time(time_t_ptr) ## time() function gets current time
## Convert to printable time string
time_val = time_t_ptr.contents.value
time_str = ctypes.string_at(libc.ctime(time_t_ptr))
return {
"timestamp": time_val,
"formatted_time": time_str.decode().strip()
}
def get_high_resolution_time():
"""Get high resolution time using clock_gettime"""
ts = timespec()
## CLOCK_REALTIME is usually 0
CLOCK_REALTIME = 0
## Call clock_gettime to fill the timespec structure
if libc.clock_gettime(CLOCK_REALTIME, ctypes.byref(ts)) != 0:
raise OSError("Failed to get time")
return {
"seconds": ts.tv_sec,
"nanoseconds": ts.tv_nsec,
"precise_time": ts.tv_sec + (ts.tv_nsec / 1_000_000_000)
}
def time_breakdown():
"""Break down the current time into its components using localtime"""
## Get current time
time_t_ptr = ctypes.pointer(ctypes.c_long())
libc.time(time_t_ptr)
## Get local time
tm_ptr = libc.localtime(time_t_ptr)
tm_struct = ctypes.cast(tm_ptr, ctypes.POINTER(tm)).contents
## Return time components
return {
"year": 1900 + tm_struct.tm_year,
"month": 1 + tm_struct.tm_mon, ## tm_mon is 0-11, we adjust to 1-12
"day": tm_struct.tm_mday,
"hour": tm_struct.tm_hour,
"minute": tm_struct.tm_min,
"second": tm_struct.tm_sec,
"weekday": tm_struct.tm_wday, ## 0 is Sunday
"yearday": tm_struct.tm_yday + 1 ## tm_yday is 0-365, we adjust to 1-366
}
## Main program
print("Time Utility using C Structures")
print("-" * 40)
## Get and display system time
sys_time = get_system_time()
print(f"System time: {sys_time['formatted_time']}")
print(f"Timestamp (seconds since epoch): {sys_time['timestamp']}")
## Get and display high-resolution time
hi_res = get_high_resolution_time()
print(f"\nHigh resolution time:")
print(f"Seconds: {hi_res['seconds']}")
print(f"Nanoseconds: {hi_res['nanoseconds']}")
print(f"Precise time: {hi_res['precise_time']}")
## Get and display time breakdown
components = time_breakdown()
print(f"\nTime breakdown:")
print(f"Date: {components['year']}-{components['month']:02d}-{components['day']:02d}")
print(f"Time: {components['hour']:02d}:{components['minute']:02d}:{components['second']:02d}")
print(f"Day of week: {components['weekday']} (0=Sunday)")
print(f"Day of year: {components['yearday']}")
## Compare with Python's datetime
now = datetime.now()
print(f"\nPython datetime: {now}")
print(f"Python timestamp: {time.time()}")
Führen Sie das Zeitdienstprogramm aus:
python3 time_utility.py
Sie sollten eine Ausgabe ähnlich dieser sehen:
Time Utility using C Structures
----------------------------------------
System time: Wed Jun 14 15:22:36 2023
Timestamp (seconds since epoch): 1686756156
High resolution time:
Seconds: 1686756156
Nanoseconds: 923456789
Precise time: 1686756156.923457
Time breakdown:
Date: 2023-06-14
Time: 15:22:36
Day of week: 3 (0=Sunday)
Day of year: 165
Python datetime: 2023-06-14 15:22:36.923499
Python timestamp: 1686756156.9234989
Verstehen des Speichermanagements mit ctypes
Bei der Arbeit mit ctypes und C-Strukturen ist es wichtig, das Speichermanagement zu verstehen. Erstellen wir ein weiteres Beispiel, memory_management.py, um dies zu demonstrieren:
import ctypes
import gc ## Garbage collector module
## Define a simple structure
class MyStruct(ctypes.Structure):
_fields_ = [
("id", ctypes.c_int),
("value", ctypes.c_double),
("name", ctypes.c_char * 32) ## Fixed-size character array
]
def demonstrate_memory_management():
print("Memory Management with ctypes")
print("-" * 40)
## Create a structure instance
my_data = MyStruct(
id=1,
value=3.14159,
name=b"Example"
)
print(f"Structure size: {ctypes.sizeof(my_data)} bytes")
print(f"Memory address: {hex(ctypes.addressof(my_data))}")
## Create a pointer to the structure
data_ptr = ctypes.pointer(my_data)
print(f"Pointer value: {hex(ctypes.cast(data_ptr, ctypes.c_void_p).value)}")
## Access through pointer
print(f"Access via pointer: id={data_ptr.contents.id}, value={data_ptr.contents.value}")
## Allocate memory for a new structure
new_struct_ptr = ctypes.POINTER(MyStruct)()
new_struct_ptr = ctypes.cast(
ctypes.create_string_buffer(ctypes.sizeof(MyStruct)),
ctypes.POINTER(MyStruct)
)
## Initialize the allocated memory
new_struct = new_struct_ptr.contents
new_struct.id = 2
new_struct.value = 2.71828
new_struct.name = b"Allocated"
print(f"\nAllocated structure memory address: {hex(ctypes.addressof(new_struct))}")
print(f"Allocated structure content: id={new_struct.id}, value={new_struct.value}, name={new_struct.name.decode()}")
## Create an array of structures
StructArray = MyStruct * 3
struct_array = StructArray(
MyStruct(10, 1.1, b"First"),
MyStruct(20, 2.2, b"Second"),
MyStruct(30, 3.3, b"Third")
)
print("\nArray of structures:")
for i, item in enumerate(struct_array):
print(f" [{i}] id={item.id}, value={item.value}, name={item.name.decode()}")
## Force garbage collection
print("\nForcing garbage collection...")
gc.collect()
## Memory is automatically managed by Python
## Run the demonstration
demonstrate_memory_management()
Führen Sie das Speichermanagementskript aus:
python3 memory_management.py
Sie sollten eine Ausgabe ähnlich dieser sehen:
Memory Management with ctypes
----------------------------------------
Structure size: 48 bytes
Memory address: 0x7f3c2e32b040
Pointer value: 0x7f3c2e32b040
Access via pointer: id=1, value=3.14159
Allocated structure memory address: 0x7f3c2e32b0a0
Allocated structure content: id=2, value=2.71828, name=Allocated
Array of structures:
[0] id=10, value=1.1, name=First
[1] id=20, value=2.2, name=Second
[2] id=30, value=3.3, name=Third
Forcing garbage collection...
In diesen Beispielen haben wir gelernt, wie man:
- C-Strukturen in Python mit
ctypesdefiniert und verwendet - Zeiger auf Strukturen erstellt und auf deren Inhalte zugreift
- Geschachtelte Strukturen und Arrays von Strukturen erstellt
- Praktische Anwendungen mithilfe von Systemzeitfunktionen erstellt
- Speicher verwaltet, wenn man mit
ctypesarbeitet
Diese Fähigkeiten sind unerlässlich, wenn man mit Windows API-Funktionen arbeitet, die häufig komplexe Datenstrukturen für den Informationsaustausch erfordern.
Erstellen einer vollständigen Systemmonitor-Anwendung
In diesem letzten Schritt werden wir unser gesamtes Wissen zusammenführen, um eine umfassende Systemmonitor-Anwendung zu erstellen. Diese Anwendung verwendet ctypes, um Systeminformationen zu sammeln, Echtzeitmetriken anzuzeigen und zu demonstrieren, wie man eine größere Python-Anwendung strukturiert, die mit Systembibliotheken interagiert.
Erstellen des Systemmonitors
Erstellen Sie eine neue Datei namens system_monitor.py mit folgendem Inhalt:
import ctypes
import os
import time
import platform
from datetime import datetime
class SystemMonitor:
"""System monitoring application using ctypes"""
def __init__(self):
"""Initialize the system monitor"""
self.libc = ctypes.CDLL("libc.so.6")
self.running = False
## Define a timespec structure for time-related functions
class timespec(ctypes.Structure):
_fields_ = [
("tv_sec", ctypes.c_long),
("tv_nsec", ctypes.c_long)
]
self.timespec = timespec
## Print basic system information
print(f"System Monitor for {platform.system()} {platform.release()}")
print(f"Python Version: {platform.python_version()}")
print(f"Machine: {platform.machine()}")
print("-" * 50)
def get_uptime(self):
"""Get system uptime information"""
try:
CLOCK_BOOTTIME = 7 ## Linux specific
time_buf = self.timespec()
if hasattr(self.libc, 'clock_gettime') and self.libc.clock_gettime(CLOCK_BOOTTIME, ctypes.byref(time_buf)) == 0:
uptime_seconds = time_buf.tv_sec
days, remainder = divmod(uptime_seconds, 86400)
hours, remainder = divmod(remainder, 3600)
minutes, seconds = divmod(remainder, 60)
return {
"total_seconds": uptime_seconds,
"days": days,
"hours": hours,
"minutes": minutes,
"seconds": seconds
}
return None
except Exception as e:
print(f"Error getting uptime: {e}")
return None
def get_memory_info(self):
"""Get memory usage information using /proc/meminfo"""
memory_info = {}
try:
with open('/proc/meminfo', 'r') as f:
for line in f:
if ':' in line:
key, value = line.split(':', 1)
## Remove 'kB' and convert to integer
value = value.strip()
if 'kB' in value:
value = int(value.split()[0]) * 1024 ## Convert to bytes
memory_info[key.strip()] = value
## Calculate memory usage percentage
if 'MemTotal' in memory_info and 'MemAvailable' in memory_info:
total = int(memory_info['MemTotal'])
available = int(memory_info['MemAvailable'])
used = total - available
memory_info['UsedPercentage'] = (used / total) * 100
return memory_info
except Exception as e:
print(f"Error getting memory info: {e}")
return {}
def get_cpu_info(self):
"""Get CPU information using /proc/stat"""
cpu_info = {'cpu_percent': 0}
try:
## We need two readings to calculate CPU usage
def get_cpu_sample():
with open('/proc/stat', 'r') as f:
line = f.readline()
cpu_values = [int(x) for x in line.split()[1:8]]
return sum(cpu_values), cpu_values[3] ## Return total and idle
## First sample
total1, idle1 = get_cpu_sample()
time.sleep(0.5) ## Wait for 0.5 second
## Second sample
total2, idle2 = get_cpu_sample()
## Calculate CPU usage
total_delta = total2 - total1
idle_delta = idle2 - idle1
if total_delta > 0:
cpu_info['cpu_percent'] = 100 * (1 - idle_delta / total_delta)
return cpu_info
except Exception as e:
print(f"Error getting CPU info: {e}")
return cpu_info
def get_disk_info(self):
"""Get disk usage information"""
try:
## Get disk usage for the root filesystem
stat = os.statvfs('/')
## Calculate total, free, and used space
total = stat.f_blocks * stat.f_frsize
free = stat.f_bfree * stat.f_frsize
used = total - free
return {
'total_bytes': total,
'free_bytes': free,
'used_bytes': used,
'used_percent': (used / total) * 100 if total > 0 else 0
}
except Exception as e:
print(f"Error getting disk info: {e}")
return {}
def get_process_count(self):
"""Count running processes"""
try:
return len([p for p in os.listdir('/proc') if p.isdigit()])
except Exception as e:
print(f"Error counting processes: {e}")
return 0
def format_bytes(self, bytes_value):
"""Format bytes into a human-readable format"""
for unit in ['B', 'KB', 'MB', 'GB', 'TB']:
if bytes_value < 1024 or unit == 'TB':
return f"{bytes_value:.2f} {unit}"
bytes_value /= 1024
def display_dashboard(self):
"""Display the system monitoring dashboard"""
## Clear the screen (works in most terminals)
print("\033c", end="")
## Display header
current_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
print(f"System Monitor - {current_time}")
print("-" * 50)
## Display uptime
uptime = self.get_uptime()
if uptime:
print(f"Uptime: {uptime['days']} days, {uptime['hours']} hours, "
f"{uptime['minutes']} minutes, {uptime['seconds']} seconds")
## Display CPU usage
cpu_info = self.get_cpu_info()
print(f"CPU Usage: {cpu_info['cpu_percent']:.1f}%")
## Display memory information
memory_info = self.get_memory_info()
if memory_info and 'MemTotal' in memory_info:
print("\nMemory Information:")
total = int(memory_info['MemTotal'])
available = int(memory_info.get('MemAvailable', 0))
used = total - available
print(f" Total: {self.format_bytes(total)}")
print(f" Used: {self.format_bytes(used)} ({memory_info.get('UsedPercentage', 0):.1f}%)")
print(f" Available: {self.format_bytes(available)}")
if 'SwapTotal' in memory_info:
swap_total = int(memory_info['SwapTotal'])
swap_free = int(memory_info.get('SwapFree', 0))
swap_used = swap_total - swap_free
if swap_total > 0:
print(f" Swap Used: {self.format_bytes(swap_used)} "
f"({(swap_used / swap_total) * 100:.1f}%)")
## Display disk information
disk_info = self.get_disk_info()
if disk_info:
print("\nDisk Information (/):")
print(f" Total: {self.format_bytes(disk_info['total_bytes'])}")
print(f" Used: {self.format_bytes(disk_info['used_bytes'])} "
f"({disk_info['used_percent']:.1f}%)")
print(f" Free: {self.format_bytes(disk_info['free_bytes'])}")
## Display process count
process_count = self.get_process_count()
print(f"\nRunning Processes: {process_count}")
print("\nPress Ctrl+C to exit")
def start_monitoring(self, interval=2):
"""Start the system monitoring with the specified refresh interval"""
self.running = True
try:
while self.running:
self.display_dashboard()
time.sleep(interval)
except KeyboardInterrupt:
print("\nMonitoring stopped.")
self.running = False
## Create and start the system monitor
if __name__ == "__main__":
monitor = SystemMonitor()
monitor.start_monitoring()
Führen Sie den Systemmonitor aus:
python3 system_monitor.py
Der Systemmonitor zeigt Echtzeitinformationen über Ihr System an, die alle 2 Sekunden aktualisiert werden. Sie sollten ein Dashboard mit Folgendem sehen:
- System-Uptime
- CPU-Auslastung
- Speicherinformationen (gesamt, verwendet, verfügbar)
- Festplattenauslastung
- Prozessanzahl
Lassen Sie den Monitor einige Momente lang laufen, um zu beobachten, wie sich die Metriken ändern, und drücken Sie dann Ctrl+C, um ihn zu beenden.
Verstehen der Systemmonitor-Struktur
Lassen Sie uns die Schlüsselkomponenten unseres Systemmonitors aufschlüsseln:
- Klassenstruktur: Verwendung der objektorientierten Programmierung zur Organisation unseres Codes
- Methodenorganisation: Trennung der Funktionalität in separate Methoden
- Fehlerbehandlung: Verwendung von try-except-Blöcken zur Behandlung potenzieller Fehler
- Datenformatierung: Konvertierung von Rohdaten in lesbare Formate
- Echtzeit-Updates: Verwendung einer Schleife mit time.sleep() für periodische Updates
Hinzufügen von Dokumentation
Fügen wir nun eine Dokumentationsdatei für unseren Systemmonitor hinzu. Erstellen Sie eine Datei namens README.md:
Python System Monitor
Eine umfassende Systemüberwachungsanwendung, die mit Python unter Verwendung von ctypes für Systeminteraktionen erstellt wurde.
Funktionen
- Echtzeit-CPU-Auslastungsüberwachung
- Speicherverfolgung
- Festplattenanalyse
- Prozessanzahl
- Anzeige der System-Uptime
Anforderungen
- Python 3.6 oder höher
- Linux-Betriebssystem
Ausführung
Führen Sie einfach das Hauptskript aus:
python system_monitor.py
### Funktionsweise
Diese Anwendung verwendet die Python-Bibliothek `ctypes`, um mit Systembibliotheken zu interagieren und auf Systeminformationen auf niedriger Ebene zuzugreifen. Sie verwendet auch das `/proc`-Dateisystem, um zusätzliche Metriken über den Systemzustand zu sammeln.
Die Überwachung erfolgt in Echtzeit mit Aktualisierungen alle 2 Sekunden (konfigurierbar).
### Architektur
Die Anwendung folgt einem objektorientierten Ansatz mit diesen Schlüsselkomponenten:
1. **SystemMonitor-Klasse**: Hauptklasse, die die Überwachung orchestriert
2. **Datenerfassungsmethoden**: Methoden zum Sammeln verschiedener Systemmetriken
3. **Anzeigemethoden**: Methoden zum Formatieren und Anzeigen der gesammelten Daten
### Erweitern des Monitors
So fügen Sie neue Überwachungsfunktionen hinzu:
1. Erstellen Sie eine neue Methode in der Klasse `SystemMonitor`, um die gewünschten Daten zu sammeln
2. Aktualisieren Sie die Methode `display_dashboard`, um die neuen Informationen anzuzeigen
3. Stellen Sie eine ordnungsgemäße Fehlerbehandlung für Robustheit sicher
### Lernressourcen
- [Python ctypes Dokumentation](https://docs.python.org/3/library/ctypes.html)
- [Linux Proc Filesystem Dokumentation](https://man7.org/linux/man-pages/man5/proc.5.html)
### Überprüfung und Zusammenfassung
Lassen Sie uns wiederholen, was wir in diesem Labor erreicht haben:
1. Wir haben gelernt, wie man die Python-Bibliothek `ctypes` verwendet, um mit Systembibliotheken zu interagieren
2. Wir haben C-Datentypen und -Strukturen in Python untersucht
3. Wir haben mehrere praktische Anwendungen erstellt:
- Abrufen grundlegender Systeminformationen
- Prozessüberwachung
- Zeitdienstprogramme
- Demonstration der Speicherverwaltung
- Umfassender Systemmonitor
4. Wir haben gelernt, wie man:
- Dynamische Bibliotheken lädt
- C-Funktionen aus Python aufruft
- C-Strukturen definiert und manipuliert
- Mit Zeigern und Speicheradressen arbeitet
- Fehler auf Systemebene behandelt
Diese Fähigkeiten bilden die Grundlage für die Arbeit mit der Windows API bei der Entwicklung auf Windows-Systemen. Die Prinzipien bleiben gleich - Sie laden Windows-spezifische Bibliotheken (wie kernel32.dll, user32.dll usw.) anstelle von libc, aber der Ansatz zum Definieren von Strukturen, zum Aufrufen von Funktionen und zur Handhabung der Daten bleibt konsistent.
Zusammenfassung
In diesem Lab haben Sie gelernt, wie Sie die ctypes-Bibliothek von Python verwenden, um mit Systembibliotheken zu interagieren und Operationen auf Systemebene durchzuführen. Obwohl das Lab in einer Linux-Umgebung durchgeführt wurde, gelten die Prinzipien und Techniken, die Sie gelernt haben, auch direkt für die Windows-API-Programmierung.
Wichtige Erkenntnisse aus diesem Lab:
Grundlagen von ctypes verstehen: Sie haben gelernt, wie man dynamische Bibliotheken lädt, C-Datentypen definiert und Systemfunktionen aus Python aufruft.
Arbeiten mit C-Strukturen: Sie haben die Erstellung und Manipulation von C-Strukturen in Python gemeistert, was für den Austausch komplexer Daten mit Systembibliotheken unerlässlich ist.
Speichermanagement: Sie haben Einblicke in Speicherallokation, Zeiger und Speichermanagement bei der Arbeit mit Systembibliotheken erhalten.
Erstellen praktischer Anwendungen: Sie haben Ihr Wissen angewendet, um nützliche Anwendungen zu erstellen, die in einem umfassenden Systemmonitor gipfeln.
Systemintegration: Sie haben gesehen, wie Python über die
ctypes-Brücke in die Systemfunktionalität auf niedriger Ebene integriert werden kann.
Diese Fähigkeiten bieten eine solide Grundlage für die Entwicklung von Anwendungen, die mit dem Betriebssystem auf niedriger Ebene interagieren müssen, sei es unter Linux oder Windows. Bei der Arbeit mit Windows-Systemen würden Sie den gleichen Ansatz verwenden, jedoch mit Windows-spezifischen Bibliotheken und API-Funktionen.
Weiteres Lernen könnte die Erforschung von Windows-spezifischen APIs für die Fensterverwaltung, grafische Oberflächen, Systemdienste oder Netzwerkfunktionen unter Verwendung der in diesem Lab erlernten Techniken beinhalten.



