Python Forum

Full Version: Dynamic File Name to a shared folder with open command in python
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
Need help for a file path to write to a file in a remote shared folder using with open command.
Below is my sample code:
import os
import glob
import io

# Deleting the older files from the shared folder

files = glob.glob(r"\\192.168.1.4\aaaa\*.xml")
for f in files:
    print('files:',f)
    os.remove(f)

file_name="testing"+".xml"

# getting Error below, not able to format the file path

with open(r"\\192.168.1.4\aaaa\" + file_name, 'w',encoding='utf-8') as wf:
    wf.write("hihi test is it works?")
    wf.close()
sjcsvat Wrote:# getting Error below, not able to format the file path
Please post the error message as well. Error messages are very useful to understand what's going on. Also you shouldn't call wf.close(). The file is automatically closed by the 'with' statement.
files = glob.glob(r"\\192.168.1.4\aaaa\*.xml")
This could not work. It's a share over network and not mounted as a real file system.

You can mount the share on Linux and work with Python on the mountpoint.
You can mount the share on Windows and work with the mounted drive.

You can also use a nice wrapper for file systems:
# python3 -m pip install fs fs.smbfs
# read the docs: https://docs.pyfilesystem.org/en/latest/index.html
import fs


with fs.open_fs("smb://USERNAME:[email protected]") as samba_share:
    # samba_share is:
    # BoundGlobber(pattern, path="/", namespaces=None, case_sensitive=True, exclude_dirs=None)
    # https://docs.pyfilesystem.org/en/latest/globbing.html#matching-files-and-directories
    samba_share.glob("**/*.xml", "/aaaa").remove()
(Jan-06-2022, 12:45 PM)DeaD_EyE Wrote: [ -> ]This could not work. It's a share over network and not mounted as a real file system.

I don't see why that should problem (on windows). Python is able to access remote shares as UNC paths through normal file operations without an explicit mount. It works fine on my windows box. I would normally do this via pathlib, but glob and the backslash r-strings don't seem to get in the way.

C:\>python
Python 3.9.0 (tags/v3.9.0:9cf6752, Oct  5 2020, 15:34:40) [MSC v.1927 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import glob
>>> files = glob.glob(r"\\10.0.0.10\USB_Storage\*")
>>> len(files)
83
>>> files[0]
'\\\\10.0.0.10\\USB_Storage\\$RECYCLE.BIN'
>>> files[3]
'\\\\10.0.0.10\\USB_Storage\\2105 Goal Tracking Meeting Dox'
(Jan-06-2022, 03:24 AM)sjcsvatt Wrote: [ -> ]with open(r"\\192.168.1.4\aaaa\" + file_name, 'w',encoding='utf-8') as wf:

For windows paths, I prefer to use forward slashes. They work just fine. You are trying to escape them via r-strings, but there's a subtlety. Because they were developed for regex escapes, they ignore backslashes at the end. Your first string has a backslash at the end that is either ignored or ends up escaping the quote.

>>> r"\\file"
'\\\\file'
>>> r"\\file\"
  File "<stdin>", line 1
    r"\\file\"
              ^
SyntaxError: EOL while scanning string literal
Better is to use use pathlib or use forward slashes. Try instead:

with open("//192.168.1.4/aaaa/" + file_name, 'w',encoding='utf-8') as wf:
(Jan-06-2022, 05:24 PM)bowlofred Wrote: [ -> ]I don't see why that should problem (on windows). Python is able to access remote shares as UNC paths through normal file operations without an explicit mount. It works fine on my windows box. I would normally do this via pathlib, but glob and the backslash r-strings don't seem to get in the way.

I didn't know, that the Windows API allows accessing via samba protocol shares.
On Linux, this does not work.

Does this work?
from pathlib import Path

server = r"\\10.0.0.10"
share = "USB_Storage"

path = Path(server, share)

print(len(path.glob("*")))
(Jan-06-2022, 10:29 PM)DeaD_EyE Wrote: [ -> ]Does this work?

Oddly to me, no. I am surprised. Doubled separators as the first element of a path are supposed to be protected, but it looks like Path() destroys them.

>>> Path("//10.0.0.10", "USB_Storage")
WindowsPath('/10.0.0.10/USB_Storage')
>>> Path(r"\\10.0.0.10", "USB_Storage")
WindowsPath('/10.0.0.10/USB_Storage')
That seems like a bug to me (or I'm not setting something somewhere). If I can get past that limitation and construct the WindowsPath object directly, it should work okay. (And I have to turn the generator into a list to get the length)

>>> p = WindowsPath('//10.0.0.10/USB_Storage')
>>> print(len(list(p.glob("*"))))
87
Ah. So Path() has to be passed a valid UNC share as the initial component (it can't assemble a UNC path from a separate server and share). So this is the functional version for me.

from pathlib import Path
unc = Path("//10.0.0.10/USB_Storage")
 
print(len(list(unc.glob("*"))))
Output:
C:\>python unc.py 87
(Jan-06-2022, 11:28 PM)bowlofred Wrote: [ -> ]And I have to turn the generator into a list to get the length
We need len_consume :-D

import pathlib


# this works
unc1 = pathlib.PureWindowsPath(r"\\host\share\file1")

# this seems to work also
unc2 = pathlib.PureWindowsPath(r"\\host\share") / "file1"

# the pathlib has support for unc paths, but only if the full path to the share is used
# concatenating the host part with share part will not work.

unc3 = pathlib.PureWindowsPath(r"\\host") / "share/dir/file"


print("OK", unc1)
print("OK", unc2)
print("FAIL", unc3)
Output:
OK \\host\share\file1 OK \\host\share\file1 FAIL \host\share\dir\file
I used PureWindowsPath because I'm on a Linux system.

For my understanding, it is important, that the str itself has the right format.

This is ok:
print(r"\\host\share\file1")
Output:
\\host\share\file1
This is not ok:
print("\\host\share\file1")
Output:
\host\share ile1
The first \ escapes the second backslash, if a raw string literal is not used.
The \f is the control character Form Feed.

Working with backslashes in string literals without the r-prefix, will cause problems.

The second important thing for UNC paths is, that they must supply in following structure: \\host\share.
In this case it was most likely the trailing backslash that was the problem (because r-strings don't unescape a trailing backslash).