py-ios-device
A python based Apple instruments protocol,you can get CPU, Memory and other metrics from real iOS devices
link: https://testerhome.com/topics/27159
Java link: https://github.com/YueChen-C/java-ios-device)
pip :
pip install py-ios-device
python version: 3.7 +
Instruments:
- Get system Memory and CPU data
- Get application Memory and CPU data
- Get FPS data FPS <= 60
- Get FPS and Jank data FPS <= 120
- Get network data
- Set the device network status. eg: 2G, 3G ,100% Loss
- Set the device behaves as though under a high thermal state
- Monitoring app start、exit、background
- Launch and Kill app
- Run xctest. eg: WebDriverAgent
- Dump core profile stack snapshot
- Analyze the core profile data stream
- Get Metal GPU Counters
- Get App Launch Lifecycle
- pull && push form the device
Other
- Profiles & Device Management. eg: Install and uninstall Fiddler certificate
- Get syslog
- Get crash log
- Get the captured packet traffic and forward it to wireshark
- App install and uninstall
- Get device battery
- Set simulate-location options
Usage:
Support iOS 17 (Command line is not supported )
pip install pymobiledevice3
sudo python3 -m pymobiledevice3 remote start-tunnel
# Recommended to use go-ios, which has better transmission performance
npm install -g go-ios
sudo ios tunnel start || ios tunnel start --userspace
curl http://127.0.0.1:60105/tunnels
from ios_device.remote.remote_lockdown import RemoteLockdownClient
from ios_device.servers.Instrument import InstrumentServer
from demo.instrument_demo.sysmontap import sysmontap
# support ios tunnel start --userspace
# [{"address":"fd17:cafe:59d4::1","rsdPort":54934,"udid":"00008101-0018242C3XXXXXXXXX","userspaceTun":true,"userspaceTunPort":60106}]
host = 'fd17:cafe:59d4::1'
port = 54934
with RemoteLockdownClient((host, port), userspace_port=60106) as rsd:
rpc = InstrumentServer(rsd).init()
sysmontap(rpc)
rpc.stop()
pip :
> pip install py-ios-device
> pyidevice --help
> pyidevice instruments --help
Get device list
$ pyidevice devices
Get device info
$ pyidevice deviceinfo --udid=xxxxxx
Get System performance data
$ pyidevice instruments monitor
Memory >> {'App Memory': '699.69 MiB', 'Cached Files': '1.48 GiB', 'Compressed': '155.17 MiB', 'Memory Used': '1.42 GiB', 'Wired Memory': '427.91 MiB', 'Swap Used': '46.25 MiB'}
Network >> {'Data Received': '4.07 GiB', 'Data Received/sec': '4.07 GiB', 'Data Sent': '2.54 GiB', 'Data Sent/sec': '2.54 GiB', 'Packets in': 2885929, 'Packets in/sec': 6031576, 'Packets Out': 2885929, 'Packets Out/sec': 2885929}
Disk >> {'Data Read': '117.91 GiB', 'Data Read/sec': 0, 'Data Written': '64.28 GiB', 'Data Written/sec': 0, 'Reads in': 9734132, 'Reads in/sec': 9734132, 'Writes Out': 6810640, 'Writes Out/sec': 6810640}
$ pyidevice instruments monitor --filter = memory
Memory >> {'App Memory': '699.69 MiB', 'Cached Files': '1.48 GiB', 'Compressed': '155.17 MiB', 'Memory Used': '1.42 GiB', 'Wired Memory': '427.91 MiB', 'Swap Used': '46.25 MiB'}
Get application performance data
$ pyidevice instruments appmonitor -b cn.rongcloud.im
{'Pid': 30897, 'Name': 'SealTalk', 'CPU': '0 %', 'Memory': '35.72 MiB', 'DiskReads': '24.12 MiB', 'DiskWrites': '2.28 MiB', 'Threads': 13}
{'Pid': 30897, 'Name': 'SealTalk', 'CPU': '3.4 %', 'Memory': '35.72 MiB', 'DiskReads': '24.12 MiB', 'DiskWrites': '2.30 MiB', 'Threads': 13}
Get custom application performance data
$ pyidevice instruments sysmontap --help
$ pyidevice instruments sysmontap -b com.tencent.xin --proc_filter physFootprint,cpuUsage --processes --sort cpuUsage # 只显示 memVirtualSize,cpuUsage 参数的进程列表,且根据 cpuUsage 字段排序
[('WeChat', {'cpuUsage': 0.03663705586691998, 'physFootprint': 2179284992, 'name': 'WeChat', 'pid': 99269})]
[('WeChat', {'cpuUsage': 0.036558268613227536, 'physFootprint': 2179284992, 'name': 'WeChat', 'pid': 99269})]
Get FPS data FPS <= 60
$ pyidevice instruments fps
{'currentTime': '2021-05-11 14:14:40.259059', 'fps': 52}
{'currentTime': '2021-05-11 14:14:40.259059', 'fps': 56}
Get FPS display data FPS <= 120
$ pyidevice instruments display
{'time': 1.393329, 'fps': 103.999274047912838, 'jank': 0, 'big_jank': 0, 'stutter': 0.0}
Get network data
$ pyidevice instruments networking
# Get all network data
"connection-update{\"RxPackets\": 2, \"RxBytes\": 148, \"TxPackets\": 2, \"TxBytes\": 263, \"RxDups\": 0, \"RxOOO\": 0, \"TxRetx\": 0, \"MinRTT\": 0.05046875, \"AvgRTT\": 0.05046875, \"ConnectionSerial\": 5}"
"connection-update{\"RxPackets\": 4, \"RxBytes\": 150, \"TxPackets\": 3, \"TxBytes\": 1431, \"RxDups\": 0, \"RxOOO\": 0, \"TxRetx\": 0, \"MinRTT\": 0.0539375, \"AvgRTT\": 0.0541875, \"ConnectionSerial\": 4}"
$ pyidevice instruments network_process -p com.tencent.xin
# Get application network data
{403: {'net.packets.delta': 119, 'time': 1620720061.0643349, 'net.tx.bytes': 366715, 'net.bytes.delta': 63721, 'net.rx.packets.delta': 47, 'net.tx.packets': 633, 'net.rx.bytes': 34532, 'net.bytes': 401247, 'net.tx.bytes.delta': 56978, 'net.rx.bytes.delta': 6743, 'net.rx.packets': 169, 'pid': 403, 'net.tx.packets.delta': 72, 'net.packets': 802}}
{403: {'net.packets.delta': 13, 'time': 1620720076.2191892, 'net.tx.bytes': 1303204, 'net.bytes.delta': 5060, 'net.rx.packets.delta': 5, 'net.tx.packets': 2083, 'net.rx.bytes': 46736, 'net.bytes': 1349940, 'net.tx.bytes.delta': 4682, 'net.rx.bytes.delta': 378, 'net.rx.packets': 379, 'pid': 403, 'net.tx.packets.delta': 8, 'net.packets': 2462}}
Set device status. iOS version > 12
$ pyidevice instruments condition get
# Get device configuration information
$ pyidevice instruments condition set -c SlowNetworkCondition -p SlowNetwork2GUrban
# Set the device network status. eg: 2G, 3G ,100% Loss
$ pyidevice instruments condition set -c ThermalCondition -p ThermalCritical
# Set the device behaves as though under a high thermal state
Listen to app notifications
$ pyidevice instruments notifications
[{'execName': 'MobileNotes', 'state_description': 'Foreground Running', 'elevated_state_description': 'Foreground Running', 'displayID': 'com.apple.mobilenotes', 'mach_absolute_time': 27205542653928, 'appName': 'Notes', 'elevated_state': 8, 'timestamp': 1620714619.1264, 'state': 8, 'pid': 99367}]
[{'execName': 'MobileNotes', 'state_description': 'Background Running', 'elevated_state_description': 'Background Running', 'displayID': 'com.apple.mobilenotes', 'mach_absolute_time': 27205678872050, 'appName': 'Notes', 'elevated_state': 4, 'timestamp': 1620714624.802145, 'state': 4, 'pid': 99367}]
[{'execName': 'MobileNotes', 'state_description': 'Background Task Suspended', 'elevated_state_description': 'Background Task Suspended', 'displayID': 'com.apple.mobilenotes', 'mach_absolute_time': 27205683486410, 'appName': 'Notes', 'elevated_state': 2, 'timestamp': 1620714624.99441, 'state': 2, 'pid': 99367}]
Dump core profile stack snapshot
$ pyidevice instruments stackshot --out stackshot.log
Analyze the core profile data stream
$ pyidevice instruments instruments core_profile --pid=1107
SealTalk(1107) PERF_THD_CSwitch (0x25010014) DBG_PERF PERF_DATA DBG_FUNC_NONE
SealTalk(1107) MACH_DISPATCH (0x1400080) DBG_MACH DBG_MACH_SCHED DBG_FUNC_NONE
SealTalk(1107) DecrSet (0x1090004) DBG_MACH DBG_MACH_EXCP_DECI DBG_FUNC_NONE
Get Metal GPU Counters
$ pyidevice instruments gpu_counters
15.132907 ALU Limiter 93.77
15.132907 Texture Sample Limiter 39.62
15.132907 Texture Write Limiter 13.87
15.132907 Buffer Read Limiter 0.01
15.132907 Buffer Write Limiter 0
15.132907 Threadgroup/Imageblock Load Limiter 17.16
15.132907 Threadgroup/Imageblock Store Limiter 10.9
15.132907 Fragment Input Interpolation Limiter 15.74
15.132907 GPU Last Level Cache Limiter 6.24
15.132907 Vertex Occupancy 0
15.132907 Fragment Occupancy 91.44
15.132907 Compute Occupancy 0
15.132907 GPU Read Bandwidth 2.65
15.132907 GPU Write Bandwidth 1.25
Get App Launch Lifecycle
$ pyidevice instruments app_lifecycle -b cn.rongcloud.im
31.20 ms Initializing-System Interface Initialization (Dyld init)
14.33 ms Initializing-Static Runtime Initialization
35.68 ms Launching-UIKit Initialization
810.46 us Launching-UIKit Scene Creation
100.64 ms Launching-didFinishLaunchingWithOptions()
2.91 ms Launching-UIKit Scene Creation
21.85 ms Launching-Initial Frame Rendering
App Thread Process ID:6506076, Total Time:207.41 ms
Other
Profiles & Device Management
$ pyidevice profiles list
{
"OrderedIdentifiers": [
"aaaff7e2b7df39eeb77bfbc0cd7a70ea99f3fd97a"
],
"ProfileManifest": {
"aaaff7e2b7df39eeb77bfbc0cd7a70ea99f3fd97a": {
"Description": "DO_NOT_TRUST_FiddlerRoot",
"IsActive": true
}
},
"ProfileMetadata": {
"aaaff7e2b7df39eeb77bfbc0cd7a70ea99f3fd97a": {
"PayloadDisplayName": "DO_NOT_TRUST_FiddlerRoot",
"PayloadRemovalDisallowed": false,
"PayloadUUID": "C8CE7BC1-F840-4616-B606-337F8CB6AE19",
"PayloadVersion": 1
}
},
"Status": "Acknowledged"
}
$ pyidevice profiles install --path Downloads/charles-certificate.pem
## install charles certificate
$ pyidevice profiles remove --name fe7371d9ce36c541ac8dee5f51f3b490b2aa98dcd95699ee44717fd5233fe7a0a
## uninstall charles certificate
get syslog
$ pyidevice syslog
# --path
# --filter
get crash syslog
$ pyidevice crash list
['.', '..', 'com.apple.appstored', 'JetsamEvent-2021-05-12-112126.ips']
$ pyidevice crash export --name JetsamEvent-2021-05-12-112126.ips
$ pyidevice crash delete --name JetsamEvent-2021-05-12-112126.ips
$ pyidevice crash shell
apps
$ pyidevice apps list
$ pyidevice apps install --ipa_path
$ pyidevice apps uninstall --bundle_id
$ pyidevice apps launch --bundle_id
$ pyidevice apps kill --bundle_id
$ pyidevice apps shell
packet capture
$ pyidevice pcapd ./test/test.pacp
$ pyidevice pcapd - | "/Applications/Wireshark.app/Contents/MacOS/Wireshark" -k -i -
# mac forword Wireshark
$ pyidevice pcapd - | "D:\Program Files\Wireshark\Wireshark.exe" -k -i -
# win forword Wireshark
device battery
$ pyidevice battery
# [Battery] time=1622777708, current=-71, voltage=4330, power=-307.43, temperature=3279
enable developer mode
$ pyidevice enable_developer_mode
using python
from ios_device.cli.base import InstrumentsBase
from ios_device.util.dtx_msg import DTXMessage
with InstrumentsBase() as rpc:
def sysmontap_callback(res: DTXMessage):
print(res.selector, res.auxiliaries)
rpc.process_attributes = ['name', 'pid']
rpc.system_attributes = rpc.device_info.sysmonSystemAttributes()
rpc.sysmontap(sysmontap_callback)
QQ :37042417
Metadata
Release files for pyidevice 2.4.30
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| pyidevice-2.4.30.tar.gz | 181.0 kB | Without provenance | Details for pyidevice-2.4.30.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| pyidevice-2.4.30-py3-none-any.whl | Python 3 | none | any | Details for pyidevice-2.4.30-py3-none-any.whl |
Total release size: 378.2 kB
Release files / pyidevice-2.4.30.tar.gz
| Download URL | pyidevice-2.4.30.tar.gz |
|---|---|
| Size | 181.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
e44e2bd99985bffb17e1931768ba0a16866b7a8bf6f7d88924b571a5078b0c6c
|
|
BLAKE2b-256 checksum How to use checksums |
2fe8da4c2a038170c1db4db2b197c2f3da687a80f764b5a3a7d588429edda608
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.0.1 CPython/3.12.10
|
Release files / pyidevice-2.4.30-py3-none-any.whl
| Download URL | pyidevice-2.4.30-py3-none-any.whl |
|---|---|
| Size | 197.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
6fdca2bdc86d1031f7178600db5d934ed57c1d6c355d5cbb7eca1ef1c9384b6d
|
|
BLAKE2b-256 checksum How to use checksums |
5db2fd9af8796f02abb45c10e8b518433ce1dcec73b7b996ee397c5616fcb951
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.0.1 CPython/3.12.10
|
Security for pyidevice 2.4.30
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.