python中的线程使用的是相同的变量

时间:2015-03-28 03:55:58

标签: python multithreading file-upload ftp

我构建了一个监视目录中的更改并将它们上传到服务器的类,它适用于一个目录。但是,我有想法使用python中的线程模块来实际观看多个目录。但是,我感到困惑,因为当我在一个位置更改文件时,它上传得很好,但是其他位置开始上传所有文件。我认为这是因为线程在某种程度上共享相同的变量或其他东西,但它仍然是不可能的,因为每个目录都有它自己专门为它工作的类的实例。

这里有一些代码:

import os, ftplib, time
from threading import Thread


class FTPSync(Thread):

    local_root = ''
    remote_root = ''
    host = ''
    user = ''
    password = ''
    content = {
        'previous': [],
        'current': []
    }
    ignore = []
    rest = 0.5
    files = []
    cwd = ''
    watching = True

    def __init__(self, local_root='', remote_root='', config={}):
        Thread.__init__(self)
        self.local_root = local_root if local_root != '' else os.path.join(os.path.dirname(__file__), os.pardir)
        self.remote_root = remote_root
        self.ignore = config['ignore'] if 'ignore' in config else []
        self.rest = config['rest'] if 'rest' in config else 0.5
        self.host, self.user, self.password = config['host'], config['user'], config['password']
        self.content['previous'] = self.read_dir(self.local_root)

    # Connect and reconnect to the server
    def connect(self, reconnect=False):
        print "Connecting..."
        self.ftp = ftplib.FTP(self.host)
        self.ftp.login(self.user, self.password)
        print "Welcome message from server:\n"
        print self.ftp.getwelcome()
        if not reconnect:
            self.cwd = self.remote_root
        self.ftp.cwd(self.cwd)

    # Start watching for local changes
    def watch(self):
        self.connect()
        while self.watching:
            self.files = []
            self.content['current'] = self.read_dir(self.local_root)
            diff = [f for f in self.content['current'] if f not in self.content['previous']]
            if len(diff) > 0:
                self.stor(diff)
                self.content['previous'] = self.content['current']
                diff = []
            time.sleep(self.rest)

    # Read a directory and its contents recursively
    def read_dir(self, dir_name, return_value=True):
        reading = os.listdir(dir_name)
        file_content = None
        for i in range(len(reading)):
            d = self._local_abspath(dir_name, reading[i])
            is_dir = os.path.isdir(d)
            file_content = open(d).read() if not is_dir else None
            offset = d.replace(self.local_root, '').replace(reading[i], '')
            if is_dir and reading[i] not in self.ignore:
                self.read_dir(d, return_value=False)
            elif not is_dir:
                info = {"name": reading[i], "content": file_content, "local_path": d, "offset": offset}
                self.files.append(info)
        if (return_value):
            return self.files
        pass

    # Here we go
    def run(self):
        self.watch()

    # Store (STOR) the files in the server
    def stor(self, files):
        nav = ''
        try:
            for f in files:
                if self._server_abspath(f['offset']) != self.cwd:
                    nav = self._server_abspath(f['offset'])
                    self.ftp.cwd(nav)
                mode = ''
                if f['name'].split('.')[-1:][0] in ['jpg', 'png', 'gif'] or os.path.getsize(f['local_path']) > 8190:
                    mode = 'binary'
                    self.ftp.storbinary('STOR {!s}'.format(f['name']), open(f['local_path']))
                else:
                    mode = 'ascii'
                    self.ftp.storlines('STOR {!s}'.format(f['name']), open(f['local_path']))
                self.cwd = self._server_abspath(f['offset'])
                print "Stored %s in %s mode" % (f['name'], mode)

        # The connection has timed out
        except ftplib.error_temp:
            self.connect(reconnect=True)
            self.stor(files)

        # A new file has been created inside a folder that does not exist in the server
        except ftplib.error_perm:
            self.ftp.mkd(nav)
            self.stor(files)

        # A new folder has been created locally, but we'll wait to update this on the server
        # when there's some content inside of it and throw us a ftplib.error_perm error, so here it'll just pass
        except IOError:
            pass

    # Return the absolute path in the server
    def _server_abspath(self, path):
        return self.remote_root + '/' + path.replace('\\', '/')

    # Return the absolute path locally
    def _local_abspath(self, dn, fn):
        return (dn +'\\'+ fn) if not dn[-1:]=='\\' else dn + fn


def start(local_root='', remote_root='', config={}):
    instance = FTPSync(local_root, remote_root, config)
    instance.start()
    return instance

这就是我使用课程的方式:

import ftpsync

config = {
    'host': 'ftp.myhost.com',
    'user': '****',
    'password': '****',
    'ignore': ['.git']
}

ftpsync.start(remote_root='/www/tst', config=config)
ftpsync.start(local_root='C:\\pygames', remote_root='/www/tst', config=config)

我想记住它适用于 ONE 目录。

0 个答案:

没有答案