I apologise if the question is so stupid but I am new in linux and python.
The point is that I need to write a python script which will detect connected usb stick and write a file to it. I use opensuse(but script shoild work with any linux distro. in ideal case). Current version can detect usb and write a file if that usb is mounted. But on my machine usb is mounted only if I browse it in file manager. Until that usb detected as a partion but without mount point. So, how can I force the system to mount usb or how can I write a file using devname or devpath or another information what I can get from hal manager. I can not use "mount" command because it requires a root permission
Simplified Source code:
import dbus, gobject, os
class DeviceAddedListener:
def __init__(self):
self.bus = dbus.SystemBus()
self.hal_manager_obj = self.bus.get_object( "org.freedesktop.Hal", "/org/freedesktop/Hal/Manager")
self.hal_manager = dbus.Interface(self.hal_manager_obj, "org.freedesktop.Hal.Manager")
self.hal_manager.connect_to_signal("DeviceAdded", self.added)
def show(self, name, udi):
d_object = self.bus.get_object('org.freedesktop.Hal', udi)
d_interface = dbus.Interface(d_object,'org.freedesktop.Hal.Device')
if d_interface.QueryCapability("volume"):
print name
props = [ "block.device", "volume.label", "volume.is_mounted", "volume.mount_point", "volume.size"]
for p in props:
print '\t', p, " = ",
try:
print d_interface.GetProperty(p)
except:
print "Fail"
def added(self, udi):
self.show("DeviceAdded", udi)
self.bus.add_signal_receiver(self.property_modified,
"PropertyModified",
"org.freedesktop.Hal.Device",
"org.freedesktop.Hal",
udi,
path_keyword = "sending_device" )
def property_modified(self, numupdates, updates, sending_device = None):
self.show("PropertyModified", sending_device)
if __name__ == '__main__':
from dbus.mainloop.glib import DBusGMainLoop
DBusGMainLoop(set_as_default=True)
loop = gobject.MainLoop()
DeviceAddedListener()
print "running"
loop.run()
The output when usb plugged in
DeviceAdded
block.device = /dev/sdb1
volume.label = #
volume.is_mounted = 0
volume.mount_point =
volume.size = 4009722368
The output when usb plugged in and mounted
block.device = /dev/sdb1
volume.label = #
volume.is_mounted = 1
volume.mount_point = /media/#
volume.size = 4009722368
Thanks for any help!
You will have to use mount because the kernel controls mounting partitions within the operating system for security reasons. You can use mount without superuser/administrator privileges. Try something like this:
Make sure that the directory (/mnt/usb1/) you are mounting to already exists, and then
mount /dev/sdb1 /mnt/usb1 -o noauto,users,rw,umask=0
There's also something called autofs that does allow automatic mounting:
http://linuxconfig.org/automatically-mount-usb-external-drive-with-autofs
The HAL it's discontinued, I think so better use UDisks to work with pen USB. Then, you can use methods FilesystemMount and FilesystemUnmount, I create one example here (https://gist.github.com/3037221) and have oficial documantation here (http://hal.freedesktop.org/docs/udisks/Device.html#Device.FilesystemMount).
Related
Eventually I want to run RTD server and retrieve the data in excel. However I have problems with the basics. So, I am presenting you a reduced problem of running a COM object in Excel First.
class HelloWorld:
_reg_clsid_ = "{7CC9F362-486D-11D1-BB48-0000E838A65F}"
_reg_desc_ = "Python Test COM Server"
_reg_progid_ = "Python.TestServer"
_public_methods_ = ['Hello']
_public_attrs_ = ['noCalls']
_readonly_attrs_ = ['noCalls']
def __init__(self):
self.noCalls = 0
def Hello(self):
self.noCalls = self.noCalls + 1
return "Hello World"
if __name__=='__main__':
import win32com.server.register
win32com.server.register.UseCommandLine(HelloWorld)
This is the basic code. It works fine the Python.TestServer is registered in HKEY_CLASSES_ROOT and I can run it through Python.
o=win32com.client.Dispatch("Python.TestServer")
o.Hello()
I tried to run through Excel(VB) as well.
Sub PythonTest()
Set PythonUtils = CreateObject("Python.TestServer")
r = PythonUtils.Hello()
MsgBox r
End Sub
I get:
My hypotheses about what is wrong are:
Something is not setup or enabled in Excel, although I have enabled Macros and ActiveX controls.
You need to define a Python interpreter?
To elaborate on the second hypothesis. I don't exactly know what Python interpreter does the COM object use to execute commands, as I have several environments. Or is everything compiled when you register??
I'm using Python 3.8.3 on a MacBook Pro (13-inch, 2016, Two Thunderbolt 3 ports)
I'm currently building an online chat and this is my person.py code:
class Person:
"""
Represents a person, hold name, socket client and client addr
"""
def __init__(self, addr, client):
self.addr = addr
self.client = client
self.name = None
def set_name(self, name):
self.name = name
def __repr__(self):
return f"Person({self.addr}, {self.name})"
And this is my server.py coding:
from threading import Thread
import time
from person import Person
# GLOBAL CONSTANTS
HOST = 'localhost'
PORT = 5500
ADDR = (HOST, PORT)
MAX_CONNECTIONS = 10
BUFSIZ = 512
# GLOBAL VARIABLES
persons = []
SERVER = socket(AF_INET, SOCK_STREAM)
SERVER.bind(ADDR) # set up server
def broadcast(msg, name):
"""
send new messages to all clients
:param msg: bytes["utf8"]
:param name: str
:return:
"""
for person in persons:
client = person.client
client.send(bytes(name, "utf8") + msg)
def client_communication(person):
"""
Thread to handle all messages from client
:param person: Person
:return: None
"""
client = person.client
# get persons name
name = client.recv(BUFSIZ).decode("utf8")
person.set_name(name)
msg = bytes(f"{name} has joined the chat!", "utf8")
broadcast(msg, "") # broadcast welcome message
while True:
try:
msg = client.recv(BUFSIZ)
if msg == bytes("{quit}", "utf8"):
client.close()
persons.remove(person)
broadcast(f"{name} has left the chat...", "")
print(f"[DISCONNECTED] {name} disconnected")
break
else:
broadcast(msg, name+": ")
print(f"{name}: ", msg.decode("utf8"))
except Exception as e:
print("[EXCEPTION]", e)
break
def wait_for_connection():
"""
Wait for connetion from new clients, start new thread once connected
:param SERVER: SOCKET
:return: None
"""
run = True
while run:
try:
client, addr = SERVER.accept()
person = Person(addr, client)
persons.append(person)
print(f"[CONNECTION] {addr} connected to the server at {time.time()}")
Thread(target=client_communication, args=(person,)).start()
except Exception as e:
print("[EXCEPTION]", e)
run = False
print("SERVER CRASHED")
if __name__ == "__main__":
SERVER.listen(MAX_CONNECTIONS) # listen for connections
print("[STARTED] Waiting for connections...")
ACCEPT_THREAD = Thread(target=wait_for_connection)
ACCEPT_THREAD.start()
ACCEPT_THREAD.join()
SERVER.close()
The problem is, everytime i try to run the program, it gives me this error:
from person import Person
ModuleNotFoundError: No module named 'person'
Does somebody know how to solve this problem?
The Problem
Most likely, this is a path-finding error. The Python Path will look in the installation's lib and site-packages folders. It will also look at the current working directory. So if you're running one file from another folder but trying to import something it will look in your running directory instead of where the file you're running. Here are two solutions to this problem.
First Solution
You can make the working directory the same as the file you're running. Giving the following file structure:
workingdir
+-- thecode
|-- server.py
+-- person.py
You have the current working directory aka where you're running your command as workingdir so a terminal might look like this:
workingdir % python thecode/server.py
Thus you need to change the working directory to thecode instead. Do cd thecode to get there.
Second Solution
You can instead add the file's directory to the python path. This is held in sys.path, and gets at the end of each python run. Thus, it is best to add to the path at the beginning of your server.py file so that person.py is in your path before you import it. Use something like the following code to do this.
import sys
import os.path
sys.path.append(os.path.split(os.path.abspath(__file__))[0])
# now you may import Person.
from person import Person
The first two modules, sys and os, are pretty standard and will give you the tools to append to the Python path. The os.path.abspath gets the absolute path of your current file, in this case it's server.py. Then os.path.split will get the trailing (all the directories) and the head (the filename) of your absolute path. Finally appending to the sys.path allows Python to find person.py in your file's directory.
Other Solutions (That probably won't be used in this case)
You can also create a custom Python package and install it using pip. This isn't very useful in this case since the import problem is just one file, however, if you ever want to create a custom Python project that other's may use this Python docs article will help.
The final solution (which admittedly I used to do and isn't the best workaround) is to put your file in a folder that's already in the Python path. In this case, it would probably be the lib folder. For me, running Python 3.8 the path is /Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8, for any Python 3.x version this will be the same but the version replaced. Python 2.x has different locations sometimes.
I can't get the following code for Detecting USB Device Insertion to work on my Windows 10 (64 bit) computer with Python 3.7.
import win32serviceutil
import win32service
import win32event
import servicemanager
import win32gui
import win32gui_struct
struct = win32gui_struct.struct
pywintypes = win32gui_struct.pywintypes
import win32con
GUID_DEVINTERFACE_USB_DEVICE = "{A5DCBF10-6530-11D2-901F-00C04FB951ED}"
DBT_DEVICEARRIVAL = 0x8000
DBT_DEVICEREMOVECOMPLETE = 0x8004
import ctypes
#
# Cut-down clone of UnpackDEV_BROADCAST from win32gui_struct, to be
# used for monkey-patching said module with correct handling
# of the "name" param of DBT_DEVTYPE_DEVICEINTERFACE
#
def _UnpackDEV_BROADCAST (lparam):
if lparam == 0: return None
hdr_format = "iii"
hdr_size = struct.calcsize (hdr_format)
hdr_buf = win32gui.PyGetMemory (lparam, hdr_size)
size, devtype, reserved = struct.unpack ("iii", hdr_buf)
# Due to x64 alignment issues, we need to use the full format string over
# the entire buffer. ie, on x64:
# calcsize('iiiP') != calcsize('iii')+calcsize('P')
buf = win32gui.PyGetMemory (lparam, size)
extra = {}
if devtype == win32con.DBT_DEVTYP_DEVICEINTERFACE:
fmt = hdr_format + "16s"
_, _, _, guid_bytes = struct.unpack (fmt, buf[:struct.calcsize(fmt)])
extra['classguid'] = pywintypes.IID (guid_bytes, True)
extra['name'] = ctypes.wstring_at (lparam + struct.calcsize(fmt))
else:
raise NotImplementedError("unknown device type %d" % (devtype,))
return win32gui_struct.DEV_BROADCAST_INFO(devtype, **extra)
win32gui_struct.UnpackDEV_BROADCAST = _UnpackDEV_BROADCAST
class DeviceEventService (win32serviceutil.ServiceFramework):
_svc_name_ = "DevEventHandler"
_svc_display_name_ = "Device Event Handler"
_svc_description_ = "Handle device notification events"
def __init__(self, args):
win32serviceutil.ServiceFramework.__init__ (self, args)
self.hWaitStop = win32event.CreateEvent (None, 0, 0, None)
#
# Specify that we're interested in device interface
# events for USB devices
#
filter = win32gui_struct.PackDEV_BROADCAST_DEVICEINTERFACE (
GUID_DEVINTERFACE_USB_DEVICE
)
self.hDevNotify = win32gui.RegisterDeviceNotification (
self.ssh, # copy of the service status handle
filter,
win32con.DEVICE_NOTIFY_SERVICE_HANDLE
)
#
# Add to the list of controls already handled by the underlying
# ServiceFramework class. We're only interested in device events
#
def GetAcceptedControls(self):
rc = win32serviceutil.ServiceFramework.GetAcceptedControls (self)
rc |= win32service.SERVICE_CONTROL_DEVICEEVENT
return rc
#
# Handle non-standard service events (including our device broadcasts)
# by logging to the Application event log
#
def SvcOtherEx(self, control, event_type, data):
if control == win32service.SERVICE_CONTROL_DEVICEEVENT:
info = win32gui_struct.UnpackDEV_BROADCAST(data)
#
# This is the key bit here where you'll presumably
# do something other than log the event. Perhaps pulse
# a named event or write to a secure pipe etc. etc.
#
if event_type == DBT_DEVICEARRIVAL:
servicemanager.LogMsg (
servicemanager.EVENTLOG_INFORMATION_TYPE,
0xF000,
("Device %s arrived" % info.name, '')
)
elif event_type == DBT_DEVICEREMOVECOMPLETE:
servicemanager.LogMsg (
servicemanager.EVENTLOG_INFORMATION_TYPE,
0xF000,
("Device %s removed" % info.name, '')
)
#
# Standard stuff for stopping and running service; nothing
# specific to device notifications
#
def SvcStop(self):
self.ReportServiceStatus (win32service.SERVICE_STOP_PENDING)
win32event.SetEvent (self.hWaitStop)
def SvcDoRun(self):
win32event.WaitForSingleObject (self.hWaitStop, win32event.INFINITE)
servicemanager.LogMsg (
servicemanager.EVENTLOG_INFORMATION_TYPE,
servicemanager.PYS_SERVICE_STOPPED,
(self._svc_name_, '')
)
if __name__=='__main__':
win32serviceutil.HandleCommandLine (DeviceEventService)
I start the script with the following command: python main.py start
Then the following error messages appear in the command prompt:
Starting service DevEventHandler
Error starting service: Access denied
I then ran the script with administrator privileges: runas /user:administrator "python main.py start"
Another error messages appear in the command prompt:
Starting service DevEventHandler
Error starting service: The specified service does not exist as an installed service.
How can the 'The specified service does not exist as an installed service' error be fixed?
I tested with Python 3.8.2 x64.
Install pywin32 (pip install pywin32)
Install the current/last version (1.5) of the WMI module from https://github.com/tjguk/wmi (pip install -e git+https://github.com/tjguk/wmi.git#egg=wmi)
run a script (test.py in my case), like:
import wmi
raw_wql = "SELECT * FROM __InstanceCreationEvent WITHIN 2 WHERE TargetInstance ISA \'Win32_USBHub\'"
c = wmi.WMI ()
watcher = c.watch_for(raw_wql=raw_wql)
while 1:
usb = watcher ()
print(usb)
plug in a USB device. Output looks like:
(wmi-py) C:\Users\USER\Source\wmi-py>py test.py
instance of Win32_USBHub
{
Caption = "USB Composite Device";
ConfigManagerErrorCode = 0;
ConfigManagerUserConfig = FALSE;
CreationClassName = "Win32_USBHub";
Description = "USB Composite Device";
...
Many thanks to the WMI module author, and the Windows nerds' discussion here Detecting USB drive insertion and removal using windows service and c#
I tried to run the script with debug argument and a message saying that service is not installed appeared.
Try first to type
python main.py install
then
python main.py start
I'm doing this to to list the available com ports in windows and unix.
Windows:
def listWindowsPorts():
serial_ports = []
has_ports = False
path = 'HARDWARE\\DEVICEMAP\\SERIALCOMM'
try:
reg = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, path,)
has_ports = True
except WindowsError:
pass
if has_ports:
for i in range(128):
try:
name, value, type = winreg.EnumValue(reg, i)
except WindowsError:
pass
else:
serial_ports.append(value)
return serial_ports
An this for UNIX (Linux-OSX):
def listUnixPorts(system):
serial_ports = []
dev_path = '/dev/'
if('osx' in system):
dev_names = ['tty.*', 'cu.*']
else:
dev_names = ['ttyACM*', 'ttyUSB*']
for dev_name in dev_names:
pattern = dev_path + dev_name
serial_ports += glob.glob(pattern)
return serial_ports
The arduino's IDE, besides displaying the COM ports, it has the ability to show the OTA "ports" automatically after configured. I'll like to know if there is a way to do this in python, so I can show serial ports and OTA ports together.
Can someone give an example or a site with this information?
I've looked in the documentation of the pyserial library but until now I haven't found the "autodiscover" feature
The answer to this question is to use a mDNS browser, in my case as I'm using python, I resolved with zeroconf
I'm trying to unmount a filesystem that I mounted using FilesystemMount, but I keep getting UnknownMethod exceptions. I've verified that I can call the method on the Device interface via D-Feet, but trying to do it via dbus directly doesn't appear to work at all. I've tried using the following arguments:
''
None
[]
['']
The following code demonstrates the problem:
import dbus
bus = dbus.SystemBus()
proxy = bus.get_object('org.freedesktop.UDisks', '/dev/fd0')
dev = dbus.Interface(proxy, 'org.freedesktop.UDisks.Device')
dev.FilesystemUnmount(['force'])
Exception:
dbus.exceptions.DBusException: org.freedesktop.DBus.Error.UnknownMethod: Method "FilesystemUmount" with signature "as" on interface "org.freedesktop.UDisks.Device" doesn't exist
Turns out that the problem is that FilesystemUnmount will only take an ObjectPath that udisks handed out. So by adding a check for that and then looking it up I got it to work. See the code below.
import dbus
path = '/dev/fd0'
bus = dbus.SystemBus()
if not isinstance(path, dbus.ObjectPath):
manager_obj = bus.get_object('org.freedesktop.UDisks',
'/org/freedesktop/UDisks')
manager = dbus.Interface(manager_obj, 'org.freedesktop.UDisks')
path = manager.FindDeviceByDeviceFile(path)
proxy = bus.get_object('org.freedesktop.UDisks', path)
dev = dbus.Interface(proxy, 'org.freedesktop.UDisks.Device')
dev.FilesystemUnmount('')