2010-02-11 62 views
4

我在寻找一些关于逻辑的帮助,代码不是很pythonic,我还在学习。我们将Z:驱动器始终映射到不同的位置。这里就是我试图完成Python - 检查网络图

1:检查旧地图上Z:说\ 192.168.1.100 \老
2:映射新的位置Z:说\ 192.168.1.200 \新
3:确保新Z:映射存在,并且仍然连接
4:如果断开连接或取消映射重新连接,并记录它

代码

90%的工作,如果我跑原样,这将取消旧驱动器并映射新驱动器,但旧驱动器的名称保持不变,即使映射到新位置并且我可以浏览它。另一个问题是我只想运行checkOldDrive一次,只是让checkDrive运行。任何建议表示赞赏。

#!/usr/bin/python 
import pywintypes 
import win32com.client 
import os.path 
import sys 
import string 
import fileinput 
import time 
import win32net 
################################################################## 
# Check for old Z: map and remove it 
# Map the new instance of Z: 
# Check if the Z: drive exists 
# if the drive exists report to status.log we are working 
# if the drive DOES NOT exist map it and report errors to the log 
################################################################### 
def checkDrive(): 
    if os.path.exists('z:'): 
     saveout = sys.stdout 
     fsock = open('status.log', 'a') 
     sys.stdout = fsock 
     print os.getenv("COMPUTERNAME"), " - ", time.ctime(), " - Connected" 
     sys.stdout = saveout 
     fsock.close() 
    else: 
     ivvinetwork = win32com.client.Dispatch('Wscript.Network') 
     network_drives = ivvinetwork.EnumNetworkDrives() 
     for mapped_drive in [network_drives.Item(i) 
          for i in range(0, network_drives.Count() -1 , 2) 
          if network_drives.Item(i)]: 
      ivvinetwork.RemoveNetworkDrive(mapped_drive, True, True) 
     drive_mapping = [ 
      ('z:', '\\\\192.168.1.100\\newmap', 'someuser', 'somepass')] 
     for drive_letter, network_path, user_name, user_pass in drive_mapping: 
      try: 
       ivvinetwork.MapNetworkDrive(drive_letter, network_path, True, user_name, user_pass) 
       saveout = sys.stdout 
       fsock = open('status.log', 'a') 
       sys.stdout = fsock 
       print os.getenv("COMPUTERNAME"), " - ", time.ctime(), " - ", drive_mapping, "Drive Has Been Mapped" 
       sys.stdout = saveout 
       fsock.close() 
      except Exception, err: 
       saveout = sys.stdout 
       fsock = open('status.log', 'a') 
       sys.stdout = fsock 
       print os.getenv("COMPUTERNAME"), " - ", time.ctime(), " - ", err 
       sys.stdout = saveout 
       fsock.close() 

def checkOldDrive(): 
    if os.path.exists('z:'): 
     ivvinetwork = win32com.client.Dispatch('Wscript.Network') 
     network_drives = ivvinetwork.EnumNetworkDrives() 
     for mapped_drive in [network_drives.Item(i) 
          for i in range(0, network_drives.Count() -1 , 2) 
          if network_drives.Item(i)]: 
      ivvinetwork.RemoveNetworkDrive(mapped_drive, True, True) 

checkOldDrive() 
checkDrive() 

回答

3

我已经放在一起的脚本基于你所布置的,我相信完成了你所描述的。

我试图用Pythonic和遵循良好编程原则的方式来做到这一点。

特别是,我已经做了以下内容:

  • 模块化多的功能集成到可重复使用的功能
  • 避免重复尽可能。我没有列出硬编码的'Z:'驱动器。我将这些留给你作为练习(如你所见)。
  • 将日志记录定义分解为一个位置(所以格式等是一致的而不是重复的)。记录模块使这一切变得简单。
  • 将所有代码移出顶层作用域(某些全局常量除外)。这允许脚本直接运行或者作为模块由另一个脚本导入。
  • 添加了一些文档字符串来帮助记录每个功能的功能。
  • 保持每个功能简洁简洁 - 因此可以在单个屏幕和单独的环境中更轻松地阅读。

当然,还有一些改进的空间,但我测试过这个脚本,它是功能性的。它应该提供一些好的教训,同时也帮助你完成你的任务。请享用。

#!/usr/bin/env python 
import os 
import time 
import win32com.client 
import logging 

old_mappings = [ 
    r'\\192.168.1.100\old', 
    ] 
new_mapping = r'\\192.168.1.200\new' 
LOG_FILENAME = 'status.log' 

def main(): 
    """ 
    Check to see if Z: is mapped to the old server; if so remove it and 
    map the Z: to the new server. 

    Then, repeatedly monitor the Z: mapping. If the Z: drive exists, 
    report to status.log that we are working. Otherwise, re-map it and 
    report errors to the log. 
    """ 
    setupLogging() 
    replaceMapping() 
    monitorMapping() 

def replaceMapping(): 
    if removeMapping(): 
     createNewMapping() 

def setupLogging(): 
    format = os.environ['COMPUTERNAME'] + " - %(asctime)s - %(message)s" 
    logging.basicConfig(filename=LOG_FILENAME, level=logging.DEBUG, format=format) 

def getCredentials(): 
    """ 
    Return one of three things: 
    - an empty tuple 
    - a tuple containing just a username (if a password is not required) 
    - a tuple containing username and password 
    """ 
    return ('someuser', 'somepass') 

def createNewMapping(): 
    network = win32com.client.Dispatch('WScript.Network') 
    params = (
     'Z:', # drive letter 
     new_mapping, # UNC path 
     True, # update profile 
     ) 
    params += getCredentials() 
    try: 
     network.MapNetworkDrive(*params) 
     msg = '{params} - Drive has been mapped' 
     logging.getLogger().info(msg.format(**vars())) 
    except Exception as e: 
     msg = 'error mapping {params}' 
     logging.getLogger().exception(msg.format(**vars())) 

def monitorMapping(): 
    while True: 
     # only check once a minute 
     time.sleep(60) 
     checkMapping() 

def checkMapping(): 
    if getDriveMappings()['Z:'] == new_mapping: 
     msg = 'Drive is still mapped' 
     logging.getLogger().info(msg.format(**vars())) 
    else: 
     replaceMapping() 

# From Python 2.6.4 docs 
from itertools import izip_longest 
def grouper(n, iterable, fillvalue=None): 
    "grouper(3, 'ABCDEFG', 'x') --> ABC DEF Gxx" 
    args = [iter(iterable)] * n 
    return izip_longest(fillvalue=fillvalue, *args) 

def getDriveMappings(): 
    """ 
    Return a dictionary of drive letter to UNC paths as mapped on the 
    system. 
    """ 
    network = win32com.client.Dispatch('WScript.Network') 
    # http://msdn.microsoft.com/en-us/library/t9zt39at%28VS.85%29.aspx 
    drives = network.EnumNetworkDrives() 
    # EnumNetworkDrives returns an even-length array of drive/unc pairs. 
    # Use grouper to convert this to a dictionary. 
    result = dict(grouper(2, drives)) 
    # Potentially several UNC paths will be connected but not assigned 
    # to any drive letter. Since only the last will be in the 
    # dictionary, remove it. 
    if '' in result: del result[''] 
    return result 

def getUNCForDrive(drive): 
    """ 
    Get the UNC path for a mapped drive. 
    Throws a KeyError if no mapping exists. 
    """ 
    return getDriveMappings()[drive.upper()] 

def removeMapping(): 
    """ 
    Remove the old drive mapping. If it is removed, or was not present, 
    return True. 
    Otherwise, return False or None. 
    """ 
    mapped_drives = getDriveMappings() 
    drive_letter = 'Z:' 
    if not drive_letter in mapped_drives: 
     return True 
    if mapped_drives[drive_letter] in old_mappings: 
     network = win32com.client.Dispatch('WScript.Network') 
     force = True 
     update_profile = True 
     network.RemoveNetworkDrive(drive_letter, force, update_profile) 
     return True 
    # return None 

if __name__ == '__main__': 
    main() 
+0

我刚刚意识到使用pairwise存在一个主要错误。这不是正确的功能,它只发生在我的环境中,因为我只映射了一个驱动器号。我会解决这个问题,并很快发布和编辑。 – 2010-02-11 15:56:05

+0

感谢'getDriveMappings()'和'getUNCForDrive()'使用win32 api检索信息,这正是我一直在寻找的内容...... :-) – tim 2016-08-09 09:52:37