Python script with acces to an SMB device

I try running a python script on my router. (First time using python)

from smb.SMBConnection import SMBConnection

I assume a module for smb connection is missing. How could I install it on my turris Omnia?

Hello @Mannshoch, you should read on the β€œvirtual environment” topics on python. For example: Python Virtual Environments: A Primer – Real Python

In short you need to create a sandboxed environment where you will be able to download / install libraries (in your case pysmb.

Currently there is a bug on omnia which prevents you to do the virtualenv the β€œeasy way”, I found a solution here: Python3 venv failed - #3 by sandor.balazsi

user@omnia:~$ python3 -m venv venv --without-pip
user@omnia:~$ source venv/bin/activate
(venv) user@omnia:~$ wget https://bootstrap.pypa.io/get-pip.py
--2023-11-14 10:20:23--  https://bootstrap.pypa.io/get-pip.py
Resolving bootstrap.pypa.io... 151.101.0.175, 151.101.64.175, 151.101.128.175, ...
Connecting to bootstrap.pypa.io|151.101.0.175|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 2632263 (2.5M) [text/x-python]
Saving to: β€˜get-pip.py’

get-pip.py                                   100%[==============================================================================================>]   2.51M  --.-KB/s    in 0.1s

2023-11-14 10:20:24 (19.5 MB/s) - β€˜get-pip.py’ saved [2632263/2632263]

(venv) user@omnia:~$ python3 get-pip.py
Collecting pip
  Downloading pip-23.3.1-py3-none-any.whl.metadata (3.5 kB)
Collecting setuptools
  Downloading setuptools-68.2.2-py3-none-any.whl.metadata (6.3 kB)
Collecting wheel
  Downloading wheel-0.41.3-py3-none-any.whl.metadata (2.2 kB)
Downloading pip-23.3.1-py3-none-any.whl (2.1 MB)
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 2.1/2.1 MB 10.1 MB/s eta 0:00:00
Downloading setuptools-68.2.2-py3-none-any.whl (807 kB)
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 807.9/807.9 kB 13.5 MB/s eta 0:00:00
Downloading wheel-0.41.3-py3-none-any.whl (65 kB)
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 65.8/65.8 kB 5.5 MB/s eta 0:00:00
Installing collected packages: wheel, setuptools, pip
Successfully installed pip-23.3.1 setuptools-68.2.2 wheel-0.41.3
(venv) user@omnia:~$ pip3 install pysmb
Collecting pysmb
  Downloading pysmb-1.2.9.1.zip (1.4 MB)
     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 1.4/1.4 MB 10.2 MB/s eta 0:00:00
  Preparing metadata (setup.py) ... done
Collecting pyasn1 (from pysmb)
  Downloading pyasn1-0.5.0-py2.py3-none-any.whl (83 kB)
     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 83.9/83.9 kB 6.9 MB/s eta 0:00:00
Collecting tqdm (from pysmb)
  Downloading tqdm-4.66.1-py3-none-any.whl.metadata (57 kB)
     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 57.6/57.6 kB 5.2 MB/s eta 0:00:00
Downloading tqdm-4.66.1-py3-none-any.whl (78 kB)
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 78.3/78.3 kB 6.9 MB/s eta 0:00:00
Building wheels for collected packages: pysmb
  Building wheel for pysmb (setup.py) ... done
  Created wheel for pysmb: filename=pysmb-1.2.9.1-py3-none-any.whl size=84803 sha256=879139aca5711dac858303a017b56d6e4872220e536c575ce7fc4c3b5aaa6c22
  Stored in directory: /tmp/.cache/wheels/79/fb/86/032760e32fad1d9277f6ace4664fd1e946cb763711948ec2bb
Successfully built pysmb
Installing collected packages: tqdm, pyasn1, pysmb
Successfully installed pyasn1-0.5.0 pysmb-1.2.9.1 tqdm-4.66.1
(venv) user@omnia:~$ python3
Python 3.9.18 (main, Oct 09 2023, 18:02:40)
[GCC 8.4.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from smb.SMBConnection import SMBConnection
>>>
(venv) user@omnia:~$

When you work on your script you always need to do the β€œsource venv/bin/activate” (venv == your name of virtual environment).

To turn off virtual environment just type β€œdeactivate”

1 Like

thanks I will try it according that.

I will use my turris Omnia as a Proxy for internet communication of a device for Backup that itself do not have Internet access. Internet β†’ Script on Turris β†’ smb share.

Do you know how the command should look like in cron if I wish to start the script?

With a virtualenvironment something like this: How to schedule a python script cron job that have packages in virtual environment? - Unix & Linux Stack Exchange

So if your virtualenv is named β€œvenv” and in your home dir, create a bash script:

#!/bin/bash
source /home/user/venv/bin/activate
cd /path/to/python_script/
python3 script.py
deactivate

After this mark it executable:

chmod 755 /home/user/bash_script.sh

And add your script to crontab (you can use luci for this):

5 4 * * * /home/user/bash_script.sh

For crontab time you can use: https://crontab.guru/

1 Like

The virtual environment seems working as you described. But I need webdavclient3 for my script. if in install it with pip I get the error:

  /tmp/pip-install-xyp1xomd/lxml_bc14a101e71146cbbe99cf59428d5c7b/setup.py:67: DeprecationWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html
    import pkg_resources
  Building lxml version 4.9.3.
  Building without Cython.
  Error: Please make sure the libxml2 and libxslt development packages are installed.
  [end of output]

Do you have an Idea how to solve that?

that package seems to be pretty old, found this: webdav4

That installed without problem.

Thanks a lot, that works.
You seems really skilled. My you also know a library for saving files to smb?
A script I have use smbprotocol, but that library do not work on turris omnia. I found pysmb, but this library seems not able to save files in chunks. (needed for huge files).
My goal at the end is to download huge files ~ 4GB from DAVS to a SMB drive.

Hello, yes if you install pysmb you can chunk in python directly. Found a example script (I did not test this, so be careful):

from smb.SMBConnection import SMBConnection

def upload_file_to_smb(local_file_path, smb_share, smb_username, smb_password, smb_host, smb_folder):
    # Create an SMB connection
    conn = SMBConnection(smb_username, smb_password, 'your-client-name', 'smb-server-name', use_ntlm_v2=True)
    
    try:
        # Connect to the SMB server
        if conn.connect(smb_host, 445):
            with open(local_file_path, 'rb') as local_file:
                # Specify the remote file path on the SMB share
                remote_file_path = f'\\{smb_folder}\\{local_file_path.split("/")[-1]}'
                
                # Create the remote file on the SMB share
                file_attributes = conn.createFile(smb_share, remote_file_path, accessMode=2)

                # Upload the file in chunks
                while True:
                    chunk = local_file.read(8192)  # 8 KB chunks
                    if not chunk:
                        break
                    conn.writeFile(smb_share, remote_file_path, chunk, file_attributes)

                # Close the remote file
                conn.closeFile(smb_share, file_attributes)

    finally:
        # Disconnect from the SMB server
        conn.close()

# Example usage
local_file_path = 'path/to/local/file.txt'
smb_share = 'your_smb_share'
smb_username = 'your_smb_username'
smb_password = 'your_smb_password'
smb_host = 'smb_server_ip'
smb_folder = 'remote_folder'

upload_file_to_smb(local_file_path, smb_share, smb_username, smb_password, smb_host, smb_folder)