File reading across network (windows)
Duncan Booth
duncan.booth at invalid.invalid
Tue Aug 12 04:47:12 EDT 2008
"Diez B. Roggisch" <deets at nospam.web.de> wrote:
>> A search suggested that the form open(r"\\server\folder\folder"), but
>> I tried many combinations guessing what it wants for that path in my
>> case (r"\\WORKGROUP\VISTA", "\\VISTA\PUBLIC", etc), and none have
>> worked so far.
The combination you want is \\server\sharename\folder\filename, so if
the Vista machine is called VISTA and has a folder shared as PUBLIC then
"\\VISTA\PUBLIC" might work. But several things can go wrong with this.
>
> You need to create network shares in windows first. Once these are
> established, *all* programs using file-IO - including python - can
> access files.
>
It isn't absolutely essential to create a network share first: most
windows apis, including those used by Python, will be very happy with a
UNC path:
>>> open(r'\\10.10.25.121\rootc\default.tag', 'r').read()
'\tTAGS\tUNSORTED\n'
The first problem you need to address is whether or not the two systems
know each other's names. This can be problematic: that's why I used an
IP address in the example I gave. If you don't have a domain controller
on the network then the machines which are on the network use a complex
system of voting to decide which will be the 'browse master', but they
don't always agree on the outcome :^)
The second problem is that if you don't establish a connection first,
you cannot specify a username and password when opening the file. That
means you get whatever the default is. Again not usually a problem if
your machines are in a domain, but in a workgroup it can be messy.
So while it is not essential, it is probably easier to establish a
connection. Of course that can be done fairly easily from within
Pythonusing win32api.NetUseAdd, ctypes, or even os.system("NET USE
\\server\share /user:yourname pa5sW0rc!")
Note that you don't need to assign a drive letter when creating the
connection, just get the authentication over with and then you can use a
UNC name for the the actual file access.
----- netuse.py -------
from __future__ import with_statement
import ctypes
from ctypes import *
from ctypes.wintypes import *
import getpass
import os
def _stdcall(dllname, restype, funcname, *argtypes):
# a decorator for a generator.
# The decorator loads the specified dll, retrieves the
# function with the specified name, set its restype and argtypes,
# it then invokes the generator which must yield twice: the first
# time it should yield the argument tuple to be passed to the dll
# function (and the yield returns the result of the call).
# It should then yield the result to be returned from the
# function call.
def decorate(func):
api = getattr(WinDLL(dllname), funcname)
api.restype = restype
api.argtypes = argtypes
def decorated(*args, **kw):
iterator = func(*args, **kw)
nargs = iterator.next()
if not isinstance(nargs, tuple):
nargs = (nargs,)
try:
res = api(*nargs)
except Exception, e:
return iterator.throw(e)
return iterator.send(res)
return decorated
return decorate
# Structure for NetUseAdd:
class USE_INFO_2(Structure):
_fields_ = [("local", LPWSTR),
("remote", LPWSTR),
("password", LPWSTR),
("status", DWORD),
("asg_type", DWORD),
("refcount", DWORD),
("usecount", DWORD),
("username", LPWSTR),
("domain", LPWSTR)]
@_stdcall("netapi32", c_int, "NetUseAdd", LPWSTR, DWORD, POINTER(USE_INFO_2), POINTER(DWORD))
def NetUseAdd(local, remote, password, asg_type=0, username=None, domainname=None):
"""Add a network connection. Returns 0 if successful"""
useinfo = USE_INFO_2(local, remote, password, 0, 0, 0, 0, username, domainname)
ParmError = DWORD()
res = yield(None, 2, useinfo, ParmError)
if res != 0:
raise RuntimeError("Could not create connection", res)
yield res
@_stdcall("netapi32", c_int, "NetUseDel", LPWSTR, LPWSTR, DWORD)
def NetUseDel(usename, forcecond=0):
res = yield(None, usename, forcecond)
if res != 0:
raise RuntimeError("Could not delete connection", res)
yield res
if __name__=='__main__':
username = "ZZZZZZ"
password = getpass.getpass("Password:")
sharename = r"\\10.10.25.121\rootc"
filename = "default.tag"
try:
with open(os.path.join(sharename, filename), "r") as f:
print f.read()
except IOError, e:
print "without net use, got", e
else:
raise RuntimeError("We connected without doing the net use!")
NetUseAdd(None, sharename, password, username=username)
with open(os.path.join(sharename, "default.tag"), "r") as f:
print f.read()
NetUseDel(sharename)
-----------------------
--
Duncan Booth http://kupuguy.blogspot.com
More information about the Python-list
mailing list