Ad

How To Access Usb On MacOS High Sierra Without Sudo Using Python

- 1 answer

I need to access a connected USB device (treated as a drive) to read and ultimately to write to in macOS. I can do what I need to do using sudo, but since this will need to be a distributed app for non technical users command line is out of the question.

This is the simplest code that fails.

#!/usr/local/bin/python
usb_drive = '/dev/disk1' #USB bsdname, verified with "system_profiler SPUSBDataType"
with open(usb_drive, 'rb', 512) as disk:
    some_bytes = disk.read(512)[4:8]
    print(some_bytes)

Failure when not run as sudo. macOS High Sierra 10.13.6 for reference.

mac:test mac$ ./test.py
Traceback (most recent call last):
  File "./test.py", line 3, in <module>
    with open(usb_drive, 'rb', 512) as disk:
IOError: [Errno 13] Permission denied: '/dev/disk1'

It seems for linux, I'd need to likely add some rules in udev. But I've been having a beast of a time finding info about this for macOS. There are some hits I've found that suggest something like chmod 4755 might work, but only if all the parent directories are setup appropriately. Other things I've found suggest that something maybe needs to be set during package installation. But I'm starting to run into a dead end of information about this.

edit: Further info. This is for a project I've inherited without any build notes or scripts. I have a working pkg installer for the previous version that allows the script to be run without sudo, and I'm hoping to replicate that installer at the end of the day.

Ad

Answer

I ended up using the elevate package as an inelegant solution to this problem.

When running the app, it will check to see if it has sudo access, if not, it will spawn a child process that will request sudo access, popping up a window asking for the sudo password. The main drawback, is that I ended up with the same app icon twice in the mac dock while it's running, but that was acceptable for the needs of this short running app.

https://pypi.org/project/elevate/

import os
from elevate import elevate

def is_root():
    return os.getuid() == 0

print("before ", is_root())
elevate()
print("after ", is_root())
Ad
source: stackoverflow.com
Ad