access remote files on server with smb protocol python3
Asked Answered
E

2

18

I have a remote server with some files.

smb://ftpsrv/public/

I can be authorized there as an anonymous user. In java I could simply write this code:

SmbFile root = new SmbFile(SMB_ROOT);

And get the ability to work with files inside (it is all I need, one row!), but I can't find how to manage with this task in Python 3, there are a lot of resources, but I think they are not relevant to my problem, because they are frequently tailored for Python 2, and old other approaches. Is there some simple way, similar to Java code above? Or can somebody provide a real working solution if, for example, I want to access file fgg.txt in smb://ftpsrv/public/ folder. Is there really a handy lib to tackle this problem?

For example on site:

import tempfile
from smb.SMBConnection import SMBConnection

# There will be some mechanism to capture userID, password, client_machine_name, server_name and server_ip
# client_machine_name can be an arbitary ASCII string
# server_name should match the remote machine name, or else the connection will be rejected
conn = SMBConnection(userID, password, client_machine_name, server_name, use_ntlm_v2 = True)
assert conn.connect(server_ip, 139)

file_obj = tempfile.NamedTemporaryFile()
file_attributes, filesize = conn.retrieveFile('smbtest', '/rfc1001.txt', file_obj)

# Retrieved file contents are inside file_obj
# Do what you need with the file_obj and then close it
# Note that the file obj is positioned at the end-of-file,
# so you might need to perform a file_obj.seek() if you need
# to read from the beginning
file_obj.close()

Do I seriously need to provide all of these details: conn = SMBConnection(userID, password, client_machine_name, server_name, use_ntlm_v2 = True)?

Eclectic answered 26/3, 2018 at 14:20 Comment(2)
Looking around on the pysmb website I found this page, is this what you need? pysmb.readthedocs.io/en/latest/api/smb_SMBHandler.htmlPetrifaction
thank you for your support, but it is not helpful. I have some problems with installation of urllib2Eclectic
P
25

A simple example of opening a file using urllib and pysmb in Python 3

import urllib
from smb.SMBHandler import SMBHandler
opener = urllib.request.build_opener(SMBHandler)
fh = opener.open('smb://host/share/file.txt')
data = fh.read()
fh.close()

I haven't got an anonymous SMB share ready to test it with, but this code should work.
urllib2 is the python 2 package, in python 3 it was renamed to just urllib and some stuff got moved around.

Petrifaction answered 27/3, 2018 at 7:14 Comment(14)
I have an exception self.sock.sendto(data, ( ip, port )) socket.gaierror: [Errno -2] Name or service not knownEclectic
That seems like you mistyped your hostname. Make sure it is int he correct format. [username:password@]hostname[:port] where everything between [ ] is optionalPetrifaction
smb://ftpsrv/public/ I have a such path and my code is opener.open('smb://ftpsrv/public/fgg.txt')Eclectic
Can you try to use ping ftpsrv on the system you are running your script on? It seems like it can't find that hostname.Petrifaction
you are right, but I can see directory with such path and name in nautilus smb://ftpsrv/public/fgg.txt. What is going on?Eclectic
I think this is because SMB likes to work with NetBIOS names (the hostname you can set in Windows). Linux by default doesn't use NetBIOS names. Nautulis knows how to handle these names when using the smb protocol. You could try to add .local to the name, otherwise you probably need to use the host file or the actual ip.Petrifaction
Thanks a lot Rick! By this command I've got ip nmblookup ftpsrv and then opener.open('smb://12*.**.**.***/public/fgg.txt') has opened my file successfully!Eclectic
Unfortunately, pysmb is very slow when it comes to big files :( Moreover, SMBHandler "opens" a file by downloading it entirely...Palaeo
@GeorgeSovetov You could use retrieveFileFromOffset to partially retrieve the file. See the documentation of SMBConnection for more info on this.Petrifaction
@RickRongen Actually I'm using pysmb extensively and make use of this function. Regarding downloading the whole file, the best recipe I came up with is to download it in parallel from 10-20 threads using retrieveFileFromOffset.Palaeo
I got this error, both for ip and hostname. urllib.error.URLError: <urlopen error SMB error: Hostname does not reply back with its machine name>Gaming
I get the same result as @PageNotFound. Hostname and IP both return this error. (Tried from MacOS and a Linux container).Painless
What is smb? How to install it?Thesaurus
@Gaming did you solved?Bathesda
E
4

I think you were asking for Linux, but for completeness I'll share how it works on Windows.

On Windows, it seems that Samba access is supported out of the box with Python's standard library functions:

import glob, os

with open(r'\\USER1-PC\Users\Public\test.txt', 'w') as f:
    f.write('hello')    # write a file on a distant Samba share

for f in glob.glob(r'\\USER1-PC\Users\**\*', recursive=True):
    print(f)   # glob works too
    if os.path.isfile(f):
        print(os.path.getmtime(f))  # we can get filesystem information
Euphemia answered 25/11, 2020 at 8:23 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.