I am using the python-smbc library on Ubuntu to access a samba share. I can access the directory structure fine, I am however not sure how to access actual files and their c
If you've managed to get the directory structure then you have a working context. The key to actually accessing files is the undocumented flags argument of Context.open
. (I haven't figured out what mode is for either but it doesn't seem necessary.)
flags
is how you tell pysmbc what type of access to the file you want. You do that by passing it an integer made by bitwise ORing (|
) flags from the os module together. Specifically the flags you want or suffixed with os.O_
(see a list in the Python documentation here).
For example, to write to a file you would set flags to os.O_WRONLY
(equiavlent to using "w"
as the mode parameter of the built in open
function) and to append to a file that might already exist use os.O_WRONLY | os.O_APPEND | os.O_CREAT
(equivalent to "a+"
).
That call will then return a file
object which you can use like any normal, local file.
I would stick with smbfs. It's only a matter of time before you want to access those shared files with something other than Python.
I also have had trouble using smbfs (random system lockdowns and reboots) and needed a quick answer.
I've also tried the smbc
module but couldn't get any data with it. I went just as far as accessing the directory structure, just like you.
Time was up and I had to deliver the code, so I took a shortcut:
I wrote a small wrapper around a "smbclient
" call. It is a hack, ugly, really ugly, but it works for my needs. It is being used in production on the company I work.
Here's some example usage:
>>> smb = smbclient.SambaClient(server="MYSERVER", share="MYSHARE",
username='foo', password='bar', domain='baz')
>>> print smb.listdir(u"/")
[u'file1.txt', u'file2.txt']
>>> f = smb.open('/file1.txt')
>>> data = f.read()
>>> f.close()
>>> smb.rename(u'/file1.txt', u'/file1.old')
The programmer before me was using a "bash" file with lots of smbclient calls, so I think my solution is at least better.
I have uploaded it here, so you can use it if you want. Bitbucket repository is here. If you find a better solution please tell me and I'll replace my code too.
Provided you have an open context (see the unit tests here)
* https://github.com/ioggstream/pysmbc/tree/master/tests
suri = 'smb://' + settings.SERVER + '/' + settings.SHARE + '/test.dat'
dpath = '/tmp/destination.out'
# open smbc uri
sfile = ctx.open(suri, os.O_RDONLY)
# open local target where to copy file
dfile = open(dpath, 'wb')
#copy file and flush
dfile.write(sfile.read())
dfile.flush()
#close both files
sfile.close()
dfile.close()
To open a context just define an authentication function
ctx = smbc.Context()
def auth_fn(server, share, workgroup, username, password):
return (workgroup, settings.USERNAME, settings.PASSWORD)
ctx.optionNoAutoAnonymousLogin = True
ctx.functionAuthData = auth_fn
If don't know if this is more clearly stated, but here's what I gleaned from this page and sorted out from a little extra Google-ing:
def do_auth (server, share, workgroup, username, password):
return ('MYDOMAIN', 'myacct', 'mypassword')
# Create the context
ctx = smbc.Context (auth_fn=do_auth)
destfile = "myfile.txt"
source = open('/home/myuser/textfile.txt', 'r')
# open a SMB/CIFS file and write to it
file = ctx.open ('smb://server/share/folder/'+destfile, os.O_CREAT | os.O_WRONLY)
for line in source:
file.write (line)
file.close()
source.close()
# open a SMB/CIFS file and read it to a local file
source = ctx.open ('smb://server/share/folder/'+destfile, os.O_RDONLY)
destfile = "/home/myuser/textfile.txt"
fle = open(destfile, 'w')
for line in source:
file.write (line)
file.close()
source.close()