Reporting new USB storage devices on Linux and macOS with Python
$begingroup$
Synopsis:
I wanted something for macOS (and Linux; maybe eventually Windows) that would simply wait for the user to connect a storage device and automatically select, or otherwise output the information to be used, read, manipulated, etc.
In its current form, it just prints to the shell, but you could assign the output to a list or variable for read/write operations and so on. It will respond to any new entries in the /dev
system directory, including most USB devices, SD Cards, Webcams, and so on. You can test it by running the script in one window, and running something like sudo touch /dev/{x,y,z}
in another.
I plan to use it to help people (those of us who are less technically inclined) migrate to Linux by automating the creation of bootable flash drives, but you can do what you like with it.
Open-ended feedback and suggestions are welcome. Please try to post example code pertaining to your suggestions, and don't be afraid to say something positive.
Usage:
user@macOS:~$ ./devlisten.py
/dev/disk2
/dev/rdisk2
/dev/disk2s1
/dev/rdisk2s1
Code:
#!/usr/bin/env python3
import os
import re
import time
import difflib
try:
os.mkdir('/tmp/dev')
except FileExistsError:
pass
except FileNotFoundError:
print('No /tmp directory found.')
exit()
except OSError:
print('Read-only file system.')
exit()
file1 = open('/tmp/dev/1', 'w')
for x in os.listdir('/dev'):
file1.write(x + 'n')
file1.close()
try:
diff = False
while diff == False:
time.sleep(0.25)
file2 = open('/tmp/dev/2', 'w')
for x in os.listdir('/dev'):
file2.write(x + 'n')
file2.close()
text1 = open('/tmp/dev/1').readlines()
text2 = open('/tmp/dev/2').readlines()
for line in difflib.unified_diff(text1, text2):
for line in re.finditer(r'(?<=^+)w.*$', line, re.MULTILINE):
print('/dev/' + line.group(0))
diff = True
except KeyboardInterrupt:
print()
exit()
python beginner python-3.x linux macos
$endgroup$
add a comment |
$begingroup$
Synopsis:
I wanted something for macOS (and Linux; maybe eventually Windows) that would simply wait for the user to connect a storage device and automatically select, or otherwise output the information to be used, read, manipulated, etc.
In its current form, it just prints to the shell, but you could assign the output to a list or variable for read/write operations and so on. It will respond to any new entries in the /dev
system directory, including most USB devices, SD Cards, Webcams, and so on. You can test it by running the script in one window, and running something like sudo touch /dev/{x,y,z}
in another.
I plan to use it to help people (those of us who are less technically inclined) migrate to Linux by automating the creation of bootable flash drives, but you can do what you like with it.
Open-ended feedback and suggestions are welcome. Please try to post example code pertaining to your suggestions, and don't be afraid to say something positive.
Usage:
user@macOS:~$ ./devlisten.py
/dev/disk2
/dev/rdisk2
/dev/disk2s1
/dev/rdisk2s1
Code:
#!/usr/bin/env python3
import os
import re
import time
import difflib
try:
os.mkdir('/tmp/dev')
except FileExistsError:
pass
except FileNotFoundError:
print('No /tmp directory found.')
exit()
except OSError:
print('Read-only file system.')
exit()
file1 = open('/tmp/dev/1', 'w')
for x in os.listdir('/dev'):
file1.write(x + 'n')
file1.close()
try:
diff = False
while diff == False:
time.sleep(0.25)
file2 = open('/tmp/dev/2', 'w')
for x in os.listdir('/dev'):
file2.write(x + 'n')
file2.close()
text1 = open('/tmp/dev/1').readlines()
text2 = open('/tmp/dev/2').readlines()
for line in difflib.unified_diff(text1, text2):
for line in re.finditer(r'(?<=^+)w.*$', line, re.MULTILINE):
print('/dev/' + line.group(0))
diff = True
except KeyboardInterrupt:
print()
exit()
python beginner python-3.x linux macos
$endgroup$
add a comment |
$begingroup$
Synopsis:
I wanted something for macOS (and Linux; maybe eventually Windows) that would simply wait for the user to connect a storage device and automatically select, or otherwise output the information to be used, read, manipulated, etc.
In its current form, it just prints to the shell, but you could assign the output to a list or variable for read/write operations and so on. It will respond to any new entries in the /dev
system directory, including most USB devices, SD Cards, Webcams, and so on. You can test it by running the script in one window, and running something like sudo touch /dev/{x,y,z}
in another.
I plan to use it to help people (those of us who are less technically inclined) migrate to Linux by automating the creation of bootable flash drives, but you can do what you like with it.
Open-ended feedback and suggestions are welcome. Please try to post example code pertaining to your suggestions, and don't be afraid to say something positive.
Usage:
user@macOS:~$ ./devlisten.py
/dev/disk2
/dev/rdisk2
/dev/disk2s1
/dev/rdisk2s1
Code:
#!/usr/bin/env python3
import os
import re
import time
import difflib
try:
os.mkdir('/tmp/dev')
except FileExistsError:
pass
except FileNotFoundError:
print('No /tmp directory found.')
exit()
except OSError:
print('Read-only file system.')
exit()
file1 = open('/tmp/dev/1', 'w')
for x in os.listdir('/dev'):
file1.write(x + 'n')
file1.close()
try:
diff = False
while diff == False:
time.sleep(0.25)
file2 = open('/tmp/dev/2', 'w')
for x in os.listdir('/dev'):
file2.write(x + 'n')
file2.close()
text1 = open('/tmp/dev/1').readlines()
text2 = open('/tmp/dev/2').readlines()
for line in difflib.unified_diff(text1, text2):
for line in re.finditer(r'(?<=^+)w.*$', line, re.MULTILINE):
print('/dev/' + line.group(0))
diff = True
except KeyboardInterrupt:
print()
exit()
python beginner python-3.x linux macos
$endgroup$
Synopsis:
I wanted something for macOS (and Linux; maybe eventually Windows) that would simply wait for the user to connect a storage device and automatically select, or otherwise output the information to be used, read, manipulated, etc.
In its current form, it just prints to the shell, but you could assign the output to a list or variable for read/write operations and so on. It will respond to any new entries in the /dev
system directory, including most USB devices, SD Cards, Webcams, and so on. You can test it by running the script in one window, and running something like sudo touch /dev/{x,y,z}
in another.
I plan to use it to help people (those of us who are less technically inclined) migrate to Linux by automating the creation of bootable flash drives, but you can do what you like with it.
Open-ended feedback and suggestions are welcome. Please try to post example code pertaining to your suggestions, and don't be afraid to say something positive.
Usage:
user@macOS:~$ ./devlisten.py
/dev/disk2
/dev/rdisk2
/dev/disk2s1
/dev/rdisk2s1
Code:
#!/usr/bin/env python3
import os
import re
import time
import difflib
try:
os.mkdir('/tmp/dev')
except FileExistsError:
pass
except FileNotFoundError:
print('No /tmp directory found.')
exit()
except OSError:
print('Read-only file system.')
exit()
file1 = open('/tmp/dev/1', 'w')
for x in os.listdir('/dev'):
file1.write(x + 'n')
file1.close()
try:
diff = False
while diff == False:
time.sleep(0.25)
file2 = open('/tmp/dev/2', 'w')
for x in os.listdir('/dev'):
file2.write(x + 'n')
file2.close()
text1 = open('/tmp/dev/1').readlines()
text2 = open('/tmp/dev/2').readlines()
for line in difflib.unified_diff(text1, text2):
for line in re.finditer(r'(?<=^+)w.*$', line, re.MULTILINE):
print('/dev/' + line.group(0))
diff = True
except KeyboardInterrupt:
print()
exit()
python beginner python-3.x linux macos
python beginner python-3.x linux macos
edited Jan 15 at 17:34
200_success
129k15153415
129k15153415
asked Jan 15 at 13:48
tjt263tjt263
33239
33239
add a comment |
add a comment |
4 Answers
4
active
oldest
votes
$begingroup$
This script might get the job done, but it is a rather crude and inefficient hack. Ideally, you should avoid polling every quarter second (or polling at all). Also, I see no reason to write any files to /tmp
.
The ideal way to do it in Linux is to use udev. If you don't want to write a persistent udev rule, or you don't have root access, you can run /sbin/udevadm monitor --udev --property
as a child process, and trigger your test whenever udevadm
offers output. For a smarter script, you can can look for the ACTION=add
line and take advantage of the information in the SUBSYSTEM=…
and DEVPATH=…
lines. DEVPATH
tells you path to the device within /sys
. But, even if you simply trigger your script only when any output appears, that would be a huge improvement over polling four times a second.
import itertools
from subprocess import Popen, PIPE
import re
import sys
KEYVALUE_RE = re.compile(r'([^=]+)=(.*)')
def events(stream):
"""
Read udev events from the stream, yielding them as dictionaries.
"""
while True:
event = dict(
KEYVALUE_RE.match(line).groups()
for line in itertools.takewhile(KEYVALUE_RE.match, stream)
)
if event:
yield event
try:
UDEVADM = ['/sbin/udevadm', 'monitor', '--udev', '--property']
with Popen(UDEVADM, stdout=PIPE, encoding='UTF-8') as udevadm:
for event in events(udevadm.stdout):
if event['ACTION'] == 'add' and event.get('DRIVER') == 'usb-storage':
print(event)
break
except KeyboardInterrupt:
sys.exit(1)
On macOS, you can get similar information by running and monitoring the output of /usr/sbin/diskutil activity
, if you are interested in storage devices. Look for lines starting with ***DiskAppeared
.
from subprocess import Popen, PIPE
import sys
try:
DISKUTIL = ['/usr/sbin/diskutil', 'activity']
with Popen(DISKUTIL, stdout=PIPE, encoding='UTF-8') as diskutil:
# Ignore events that describe the present state
for line in diskutil.stdout:
if line.startswith('***DAIdle'):
break
# Detect the first subsequent "Disk Appeared" event
for line in diskutil.stdout:
if line.startswith('***DiskAppeared'):
print(line)
break
except KeyboardInterrupt:
sys.exit(1)
If you are interested in non-storage devices as well, then you could take advantage of the File System Events API, possibly through the MacFSEvents Python package or the cross-platform fswatch program.
$endgroup$
add a comment |
$begingroup$
Prefer to use $TMPDIR
if set, and /tmp
only as a fallback. That's the standard practice that allows users to have separate, private temporary directories, for example, so don't subvert it! You probably ought to consider tempfile.TemporaryDirectory()
as an alternative.
Error messages should go to standard error channel, not standard output.
I don't know Mac OS, but on Linux I'd expect you to wait on inotify
, rather than polling the dev
directory. There's a choice of Python interface to inotify
, but I'm not in a position to recommend any in particular.
$endgroup$
2
$begingroup$
macOS has FSEvents (en.wikipedia.org/wiki/FSEvents). I don't know much about it.
$endgroup$
– tjt263
Jan 15 at 18:17
add a comment |
$begingroup$
context managers
You should really open and close files with the
with
statement see PEP343
if __name__ == '__main__':
guard
Python idiom is to use a guard to ensure main is not run when being imported by another script
tempfile
As mentioned by @Toby already, there is module for creating Temporary files/directories
Why does it need to be in a file though?
You could create a list of filenames and poll for changes
And compare the lists instead of the files
$endgroup$
$begingroup$
It doesn't have to be stored in a file. I just thought it would be better than storing it in RAM the whole time.
$endgroup$
– tjt263
Jan 15 at 18:01
3
$begingroup$
@tjt263 Why would it?
$endgroup$
– Konrad Rudolph
Jan 16 at 0:46
add a comment |
$begingroup$
Another point I didn't see mentioned:
try:
os.mkdir('/tmp/dev')
except FileExistsError:
pass
except
blocks with pass
are usually a sign that there is probably a better way. In this case, assuming you are using Python 3.2 or later, is to use os.makedirs
with the exist_ok
argument set to True
:
os.makedirs('/tmp/dev', exist_ok=True)
$endgroup$
$begingroup$
Why's that better? What's the difference?
$endgroup$
– tjt263
Jan 15 at 22:48
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
return StackExchange.using("mathjaxEditing", function () {
StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix) {
StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
});
});
}, "mathjax-editing");
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "196"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f211546%2freporting-new-usb-storage-devices-on-linux-and-macos-with-python%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
4 Answers
4
active
oldest
votes
4 Answers
4
active
oldest
votes
active
oldest
votes
active
oldest
votes
$begingroup$
This script might get the job done, but it is a rather crude and inefficient hack. Ideally, you should avoid polling every quarter second (or polling at all). Also, I see no reason to write any files to /tmp
.
The ideal way to do it in Linux is to use udev. If you don't want to write a persistent udev rule, or you don't have root access, you can run /sbin/udevadm monitor --udev --property
as a child process, and trigger your test whenever udevadm
offers output. For a smarter script, you can can look for the ACTION=add
line and take advantage of the information in the SUBSYSTEM=…
and DEVPATH=…
lines. DEVPATH
tells you path to the device within /sys
. But, even if you simply trigger your script only when any output appears, that would be a huge improvement over polling four times a second.
import itertools
from subprocess import Popen, PIPE
import re
import sys
KEYVALUE_RE = re.compile(r'([^=]+)=(.*)')
def events(stream):
"""
Read udev events from the stream, yielding them as dictionaries.
"""
while True:
event = dict(
KEYVALUE_RE.match(line).groups()
for line in itertools.takewhile(KEYVALUE_RE.match, stream)
)
if event:
yield event
try:
UDEVADM = ['/sbin/udevadm', 'monitor', '--udev', '--property']
with Popen(UDEVADM, stdout=PIPE, encoding='UTF-8') as udevadm:
for event in events(udevadm.stdout):
if event['ACTION'] == 'add' and event.get('DRIVER') == 'usb-storage':
print(event)
break
except KeyboardInterrupt:
sys.exit(1)
On macOS, you can get similar information by running and monitoring the output of /usr/sbin/diskutil activity
, if you are interested in storage devices. Look for lines starting with ***DiskAppeared
.
from subprocess import Popen, PIPE
import sys
try:
DISKUTIL = ['/usr/sbin/diskutil', 'activity']
with Popen(DISKUTIL, stdout=PIPE, encoding='UTF-8') as diskutil:
# Ignore events that describe the present state
for line in diskutil.stdout:
if line.startswith('***DAIdle'):
break
# Detect the first subsequent "Disk Appeared" event
for line in diskutil.stdout:
if line.startswith('***DiskAppeared'):
print(line)
break
except KeyboardInterrupt:
sys.exit(1)
If you are interested in non-storage devices as well, then you could take advantage of the File System Events API, possibly through the MacFSEvents Python package or the cross-platform fswatch program.
$endgroup$
add a comment |
$begingroup$
This script might get the job done, but it is a rather crude and inefficient hack. Ideally, you should avoid polling every quarter second (or polling at all). Also, I see no reason to write any files to /tmp
.
The ideal way to do it in Linux is to use udev. If you don't want to write a persistent udev rule, or you don't have root access, you can run /sbin/udevadm monitor --udev --property
as a child process, and trigger your test whenever udevadm
offers output. For a smarter script, you can can look for the ACTION=add
line and take advantage of the information in the SUBSYSTEM=…
and DEVPATH=…
lines. DEVPATH
tells you path to the device within /sys
. But, even if you simply trigger your script only when any output appears, that would be a huge improvement over polling four times a second.
import itertools
from subprocess import Popen, PIPE
import re
import sys
KEYVALUE_RE = re.compile(r'([^=]+)=(.*)')
def events(stream):
"""
Read udev events from the stream, yielding them as dictionaries.
"""
while True:
event = dict(
KEYVALUE_RE.match(line).groups()
for line in itertools.takewhile(KEYVALUE_RE.match, stream)
)
if event:
yield event
try:
UDEVADM = ['/sbin/udevadm', 'monitor', '--udev', '--property']
with Popen(UDEVADM, stdout=PIPE, encoding='UTF-8') as udevadm:
for event in events(udevadm.stdout):
if event['ACTION'] == 'add' and event.get('DRIVER') == 'usb-storage':
print(event)
break
except KeyboardInterrupt:
sys.exit(1)
On macOS, you can get similar information by running and monitoring the output of /usr/sbin/diskutil activity
, if you are interested in storage devices. Look for lines starting with ***DiskAppeared
.
from subprocess import Popen, PIPE
import sys
try:
DISKUTIL = ['/usr/sbin/diskutil', 'activity']
with Popen(DISKUTIL, stdout=PIPE, encoding='UTF-8') as diskutil:
# Ignore events that describe the present state
for line in diskutil.stdout:
if line.startswith('***DAIdle'):
break
# Detect the first subsequent "Disk Appeared" event
for line in diskutil.stdout:
if line.startswith('***DiskAppeared'):
print(line)
break
except KeyboardInterrupt:
sys.exit(1)
If you are interested in non-storage devices as well, then you could take advantage of the File System Events API, possibly through the MacFSEvents Python package or the cross-platform fswatch program.
$endgroup$
add a comment |
$begingroup$
This script might get the job done, but it is a rather crude and inefficient hack. Ideally, you should avoid polling every quarter second (or polling at all). Also, I see no reason to write any files to /tmp
.
The ideal way to do it in Linux is to use udev. If you don't want to write a persistent udev rule, or you don't have root access, you can run /sbin/udevadm monitor --udev --property
as a child process, and trigger your test whenever udevadm
offers output. For a smarter script, you can can look for the ACTION=add
line and take advantage of the information in the SUBSYSTEM=…
and DEVPATH=…
lines. DEVPATH
tells you path to the device within /sys
. But, even if you simply trigger your script only when any output appears, that would be a huge improvement over polling four times a second.
import itertools
from subprocess import Popen, PIPE
import re
import sys
KEYVALUE_RE = re.compile(r'([^=]+)=(.*)')
def events(stream):
"""
Read udev events from the stream, yielding them as dictionaries.
"""
while True:
event = dict(
KEYVALUE_RE.match(line).groups()
for line in itertools.takewhile(KEYVALUE_RE.match, stream)
)
if event:
yield event
try:
UDEVADM = ['/sbin/udevadm', 'monitor', '--udev', '--property']
with Popen(UDEVADM, stdout=PIPE, encoding='UTF-8') as udevadm:
for event in events(udevadm.stdout):
if event['ACTION'] == 'add' and event.get('DRIVER') == 'usb-storage':
print(event)
break
except KeyboardInterrupt:
sys.exit(1)
On macOS, you can get similar information by running and monitoring the output of /usr/sbin/diskutil activity
, if you are interested in storage devices. Look for lines starting with ***DiskAppeared
.
from subprocess import Popen, PIPE
import sys
try:
DISKUTIL = ['/usr/sbin/diskutil', 'activity']
with Popen(DISKUTIL, stdout=PIPE, encoding='UTF-8') as diskutil:
# Ignore events that describe the present state
for line in diskutil.stdout:
if line.startswith('***DAIdle'):
break
# Detect the first subsequent "Disk Appeared" event
for line in diskutil.stdout:
if line.startswith('***DiskAppeared'):
print(line)
break
except KeyboardInterrupt:
sys.exit(1)
If you are interested in non-storage devices as well, then you could take advantage of the File System Events API, possibly through the MacFSEvents Python package or the cross-platform fswatch program.
$endgroup$
This script might get the job done, but it is a rather crude and inefficient hack. Ideally, you should avoid polling every quarter second (or polling at all). Also, I see no reason to write any files to /tmp
.
The ideal way to do it in Linux is to use udev. If you don't want to write a persistent udev rule, or you don't have root access, you can run /sbin/udevadm monitor --udev --property
as a child process, and trigger your test whenever udevadm
offers output. For a smarter script, you can can look for the ACTION=add
line and take advantage of the information in the SUBSYSTEM=…
and DEVPATH=…
lines. DEVPATH
tells you path to the device within /sys
. But, even if you simply trigger your script only when any output appears, that would be a huge improvement over polling four times a second.
import itertools
from subprocess import Popen, PIPE
import re
import sys
KEYVALUE_RE = re.compile(r'([^=]+)=(.*)')
def events(stream):
"""
Read udev events from the stream, yielding them as dictionaries.
"""
while True:
event = dict(
KEYVALUE_RE.match(line).groups()
for line in itertools.takewhile(KEYVALUE_RE.match, stream)
)
if event:
yield event
try:
UDEVADM = ['/sbin/udevadm', 'monitor', '--udev', '--property']
with Popen(UDEVADM, stdout=PIPE, encoding='UTF-8') as udevadm:
for event in events(udevadm.stdout):
if event['ACTION'] == 'add' and event.get('DRIVER') == 'usb-storage':
print(event)
break
except KeyboardInterrupt:
sys.exit(1)
On macOS, you can get similar information by running and monitoring the output of /usr/sbin/diskutil activity
, if you are interested in storage devices. Look for lines starting with ***DiskAppeared
.
from subprocess import Popen, PIPE
import sys
try:
DISKUTIL = ['/usr/sbin/diskutil', 'activity']
with Popen(DISKUTIL, stdout=PIPE, encoding='UTF-8') as diskutil:
# Ignore events that describe the present state
for line in diskutil.stdout:
if line.startswith('***DAIdle'):
break
# Detect the first subsequent "Disk Appeared" event
for line in diskutil.stdout:
if line.startswith('***DiskAppeared'):
print(line)
break
except KeyboardInterrupt:
sys.exit(1)
If you are interested in non-storage devices as well, then you could take advantage of the File System Events API, possibly through the MacFSEvents Python package or the cross-platform fswatch program.
edited Jan 15 at 20:19
answered Jan 15 at 18:48
200_success200_success
129k15153415
129k15153415
add a comment |
add a comment |
$begingroup$
Prefer to use $TMPDIR
if set, and /tmp
only as a fallback. That's the standard practice that allows users to have separate, private temporary directories, for example, so don't subvert it! You probably ought to consider tempfile.TemporaryDirectory()
as an alternative.
Error messages should go to standard error channel, not standard output.
I don't know Mac OS, but on Linux I'd expect you to wait on inotify
, rather than polling the dev
directory. There's a choice of Python interface to inotify
, but I'm not in a position to recommend any in particular.
$endgroup$
2
$begingroup$
macOS has FSEvents (en.wikipedia.org/wiki/FSEvents). I don't know much about it.
$endgroup$
– tjt263
Jan 15 at 18:17
add a comment |
$begingroup$
Prefer to use $TMPDIR
if set, and /tmp
only as a fallback. That's the standard practice that allows users to have separate, private temporary directories, for example, so don't subvert it! You probably ought to consider tempfile.TemporaryDirectory()
as an alternative.
Error messages should go to standard error channel, not standard output.
I don't know Mac OS, but on Linux I'd expect you to wait on inotify
, rather than polling the dev
directory. There's a choice of Python interface to inotify
, but I'm not in a position to recommend any in particular.
$endgroup$
2
$begingroup$
macOS has FSEvents (en.wikipedia.org/wiki/FSEvents). I don't know much about it.
$endgroup$
– tjt263
Jan 15 at 18:17
add a comment |
$begingroup$
Prefer to use $TMPDIR
if set, and /tmp
only as a fallback. That's the standard practice that allows users to have separate, private temporary directories, for example, so don't subvert it! You probably ought to consider tempfile.TemporaryDirectory()
as an alternative.
Error messages should go to standard error channel, not standard output.
I don't know Mac OS, but on Linux I'd expect you to wait on inotify
, rather than polling the dev
directory. There's a choice of Python interface to inotify
, but I'm not in a position to recommend any in particular.
$endgroup$
Prefer to use $TMPDIR
if set, and /tmp
only as a fallback. That's the standard practice that allows users to have separate, private temporary directories, for example, so don't subvert it! You probably ought to consider tempfile.TemporaryDirectory()
as an alternative.
Error messages should go to standard error channel, not standard output.
I don't know Mac OS, but on Linux I'd expect you to wait on inotify
, rather than polling the dev
directory. There's a choice of Python interface to inotify
, but I'm not in a position to recommend any in particular.
answered Jan 15 at 14:08
Toby SpeightToby Speight
23.9k739113
23.9k739113
2
$begingroup$
macOS has FSEvents (en.wikipedia.org/wiki/FSEvents). I don't know much about it.
$endgroup$
– tjt263
Jan 15 at 18:17
add a comment |
2
$begingroup$
macOS has FSEvents (en.wikipedia.org/wiki/FSEvents). I don't know much about it.
$endgroup$
– tjt263
Jan 15 at 18:17
2
2
$begingroup$
macOS has FSEvents (en.wikipedia.org/wiki/FSEvents). I don't know much about it.
$endgroup$
– tjt263
Jan 15 at 18:17
$begingroup$
macOS has FSEvents (en.wikipedia.org/wiki/FSEvents). I don't know much about it.
$endgroup$
– tjt263
Jan 15 at 18:17
add a comment |
$begingroup$
context managers
You should really open and close files with the
with
statement see PEP343
if __name__ == '__main__':
guard
Python idiom is to use a guard to ensure main is not run when being imported by another script
tempfile
As mentioned by @Toby already, there is module for creating Temporary files/directories
Why does it need to be in a file though?
You could create a list of filenames and poll for changes
And compare the lists instead of the files
$endgroup$
$begingroup$
It doesn't have to be stored in a file. I just thought it would be better than storing it in RAM the whole time.
$endgroup$
– tjt263
Jan 15 at 18:01
3
$begingroup$
@tjt263 Why would it?
$endgroup$
– Konrad Rudolph
Jan 16 at 0:46
add a comment |
$begingroup$
context managers
You should really open and close files with the
with
statement see PEP343
if __name__ == '__main__':
guard
Python idiom is to use a guard to ensure main is not run when being imported by another script
tempfile
As mentioned by @Toby already, there is module for creating Temporary files/directories
Why does it need to be in a file though?
You could create a list of filenames and poll for changes
And compare the lists instead of the files
$endgroup$
$begingroup$
It doesn't have to be stored in a file. I just thought it would be better than storing it in RAM the whole time.
$endgroup$
– tjt263
Jan 15 at 18:01
3
$begingroup$
@tjt263 Why would it?
$endgroup$
– Konrad Rudolph
Jan 16 at 0:46
add a comment |
$begingroup$
context managers
You should really open and close files with the
with
statement see PEP343
if __name__ == '__main__':
guard
Python idiom is to use a guard to ensure main is not run when being imported by another script
tempfile
As mentioned by @Toby already, there is module for creating Temporary files/directories
Why does it need to be in a file though?
You could create a list of filenames and poll for changes
And compare the lists instead of the files
$endgroup$
context managers
You should really open and close files with the
with
statement see PEP343
if __name__ == '__main__':
guard
Python idiom is to use a guard to ensure main is not run when being imported by another script
tempfile
As mentioned by @Toby already, there is module for creating Temporary files/directories
Why does it need to be in a file though?
You could create a list of filenames and poll for changes
And compare the lists instead of the files
answered Jan 15 at 14:29
LudisposedLudisposed
7,48921959
7,48921959
$begingroup$
It doesn't have to be stored in a file. I just thought it would be better than storing it in RAM the whole time.
$endgroup$
– tjt263
Jan 15 at 18:01
3
$begingroup$
@tjt263 Why would it?
$endgroup$
– Konrad Rudolph
Jan 16 at 0:46
add a comment |
$begingroup$
It doesn't have to be stored in a file. I just thought it would be better than storing it in RAM the whole time.
$endgroup$
– tjt263
Jan 15 at 18:01
3
$begingroup$
@tjt263 Why would it?
$endgroup$
– Konrad Rudolph
Jan 16 at 0:46
$begingroup$
It doesn't have to be stored in a file. I just thought it would be better than storing it in RAM the whole time.
$endgroup$
– tjt263
Jan 15 at 18:01
$begingroup$
It doesn't have to be stored in a file. I just thought it would be better than storing it in RAM the whole time.
$endgroup$
– tjt263
Jan 15 at 18:01
3
3
$begingroup$
@tjt263 Why would it?
$endgroup$
– Konrad Rudolph
Jan 16 at 0:46
$begingroup$
@tjt263 Why would it?
$endgroup$
– Konrad Rudolph
Jan 16 at 0:46
add a comment |
$begingroup$
Another point I didn't see mentioned:
try:
os.mkdir('/tmp/dev')
except FileExistsError:
pass
except
blocks with pass
are usually a sign that there is probably a better way. In this case, assuming you are using Python 3.2 or later, is to use os.makedirs
with the exist_ok
argument set to True
:
os.makedirs('/tmp/dev', exist_ok=True)
$endgroup$
$begingroup$
Why's that better? What's the difference?
$endgroup$
– tjt263
Jan 15 at 22:48
add a comment |
$begingroup$
Another point I didn't see mentioned:
try:
os.mkdir('/tmp/dev')
except FileExistsError:
pass
except
blocks with pass
are usually a sign that there is probably a better way. In this case, assuming you are using Python 3.2 or later, is to use os.makedirs
with the exist_ok
argument set to True
:
os.makedirs('/tmp/dev', exist_ok=True)
$endgroup$
$begingroup$
Why's that better? What's the difference?
$endgroup$
– tjt263
Jan 15 at 22:48
add a comment |
$begingroup$
Another point I didn't see mentioned:
try:
os.mkdir('/tmp/dev')
except FileExistsError:
pass
except
blocks with pass
are usually a sign that there is probably a better way. In this case, assuming you are using Python 3.2 or later, is to use os.makedirs
with the exist_ok
argument set to True
:
os.makedirs('/tmp/dev', exist_ok=True)
$endgroup$
Another point I didn't see mentioned:
try:
os.mkdir('/tmp/dev')
except FileExistsError:
pass
except
blocks with pass
are usually a sign that there is probably a better way. In this case, assuming you are using Python 3.2 or later, is to use os.makedirs
with the exist_ok
argument set to True
:
os.makedirs('/tmp/dev', exist_ok=True)
answered Jan 15 at 19:21
DeepSpaceDeepSpace
29519
29519
$begingroup$
Why's that better? What's the difference?
$endgroup$
– tjt263
Jan 15 at 22:48
add a comment |
$begingroup$
Why's that better? What's the difference?
$endgroup$
– tjt263
Jan 15 at 22:48
$begingroup$
Why's that better? What's the difference?
$endgroup$
– tjt263
Jan 15 at 22:48
$begingroup$
Why's that better? What's the difference?
$endgroup$
– tjt263
Jan 15 at 22:48
add a comment |
Thanks for contributing an answer to Code Review Stack Exchange!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
Use MathJax to format equations. MathJax reference.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f211546%2freporting-new-usb-storage-devices-on-linux-and-macos-with-python%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown