在 argparse 中从变量而不是命令行获取值

Posted

技术标签:

【中文标题】在 argparse 中从变量而不是命令行获取值【英文标题】:Get value from variable instead of command line in argparse 【发布时间】:2016-12-20 03:39:39 【问题描述】:

我正在使用 pynetdicom 脚本从 dcm4chee 获取数据。 要运行脚本,我需要从命令行传递参数。 但是我已经在某个变量或其他对象中拥有该值,我需要从那里使用,但我不知道如何将该值传递给解析器,或者是否可以不解析。

请帮助我了解如何使用一些变量而不是通过命令行传递值。

脚本:

 #!/usr/bin/python

"""
For help on usage, 
python qrscu.py -h 

"""

import argparse
from netdicom.applicationentity import AE
from netdicom.SOPclass import *
from dicom.dataset import Dataset, FileDataset
from dicom.UID import ExplicitVRLittleEndian, ImplicitVRLittleEndian, ExplicitVRBigEndian
import netdicom
import tempfile

# parse commandline
parser = argparse.ArgumentParser(description='storage SCU example')
print "parser", parser
parser.add_argument('remotehost')
parser.add_argument('remoteport', type=int)
parser.add_argument('searchstring')
parser.add_argument('-p', help='local server port', type=int, default=9999)
parser.add_argument('-aet', help='calling AE title', default='PYNETDICOM')
parser.add_argument('-aec', help='called AE title', default='REMOTESCU')
parser.add_argument('-implicit', action='store_true', help='negociate implicit transfer syntax only', default=False)
parser.add_argument('-explicit', action='store_true', help='negociate explicit transfer syntax only', default=False)

args = parser.parse_args()
print "args :::: ", type(args), args

if args.implicit:
    ts = [ImplicitVRLittleEndian]
elif args.explicit:
    ts = [ExplicitVRLittleEndian]
else:
    ts = [
        ExplicitVRLittleEndian, 
        ImplicitVRLittleEndian, 
        ExplicitVRBigEndian
        ]

# call back
def OnAssociateResponse(association):
    print "Association response received"


def OnAssociateRequest(association):
    print "Association resquested"
    return True

def OnReceiveStore(SOPClass, DS):
    print "Received C-STORE", DS.PatientName
    try:
        # do something with dataset. For instance, store it.
        file_meta = Dataset()
        file_meta.MediaStorageSOPClassUID = '1.2.840.10008.5.1.4.1.1.2'
        file_meta.MediaStorageSOPInstanceUID = "1.2.3"  # !! Need valid UID here
        file_meta.ImplementationClassUID = "1.2.3.4"  # !!! Need valid UIDs here
        filename = '%s/%s.dcm' % (tempfile.gettempdir(), DS.SOPInstanceUID)
        ds = FileDataset(filename, , file_meta=file_meta, preamble="\0" * 128)
        ds.update(DS)
        ds.save_as(filename)
        print "File %s written" % filename
    except:
        pass
    # must return appropriate status
    return SOPClass.Success

# create application entity with Find and Move SOP classes as SCU and
# Storage SOP class as SCP
MyAE = AE(args.aet, args.p, [PatientRootFindSOPClass,
                             PatientRootMoveSOPClass,
                             VerificationSOPClass], [StorageSOPClass], ts)
MyAE.OnAssociateResponse = OnAssociateResponse
MyAE.OnAssociateRequest = OnAssociateRequest
MyAE.OnReceiveStore = OnReceiveStore
MyAE.start()


# remote application entity
RemoteAE = dict(Address=args.remotehost, Port=args.remoteport, AET=args.aec)

# create association with remote AE
print "Request association"
assoc = MyAE.RequestAssociation(RemoteAE)

# perform a DICOM ECHO
print "DICOM Echo ... ",
if assoc:
    st = assoc.VerificationSOPClass.SCU(1)
    print 'done with status "%s"' % st

    print "DICOM FindSCU ... ",
    print "\n\n----------------------------------------------------------------------\n\n"
    d = Dataset()
    d.StudyDate = args.searchstring
    d.QueryRetrieveLevel = "STUDY"
    d.PatientID = "*"
    study = [x[1] for x in assoc.PatientRootFindSOPClass.SCU(d, 1)][:-1]
    print 'done with status "%s"' % st
    print "\n\n\n Cont...", study
    print "\n\n----------------------------------------------------------------------\n\n"
    # loop on patients
    for pp in study:
        print "\n\n----------------------Pateint Detals------------------------------------------------\n\n"
        print "%s - %s" % (pp.StudyDate, pp.PatientID)
        # find studies
        d = Dataset()
        d.PatientID = pp.PatientID
        d.QueryRetrieveLevel = "STUDY"
        d.PatientName = ""
        d.StudyInstanceUID = ""
        d.StudyDate = ""
        d.StudyTime = ""
        d.StudyID = ""
        d.ModalitiesInStudy = ""
        d.StudyDescription = ""
        studies = [x[1] for x in assoc.PatientRootFindSOPClass.SCU(d, 1)][:-1]
        # loop on studies
        for st in studies:
            print "\n study :: ", studies
            print "\n\n---------------------------Study---------------------------\n\n"
            print "    %s - %s %s" % (st.StudyDescription, st.StudyDate, st.StudyTime)
            d = Dataset()
            d.QueryRetrieveLevel = "SERIES"
            d.StudyInstanceUID = st.StudyInstanceUID
            d.SeriesInstanceUID = ""
            d.InstanceNumber = ""
            d.Modality = ""
            d.SeriesNumber = ""
            d.SeriesDescription = ""
            d.AccessionNumber = ""
            d.SeriesDate = ""
            d.SeriesTime = ""
            d.SeriesID = ""
            d.NumberOfSeriesRelatedInstances = ""
            series = [x[1] for x in assoc.PatientRootFindSOPClass.SCU(d, 1)][:-1]

            # print series uid and number of instances
            if series:
                for se in series:
                    print "\n\n---------------------------Series---------------------------\n\n"
                    print "\n\n\n series", se
                    print " %15s - %10s - %35s - %5s" % (se.SeriesNumber, se.Modality, se.SeriesDescription, se.NumberOfSeriesRelatedInstances)

    print "Release association"
    assoc.Release(0)

    # done
    MyAE.Quit()
else:
    print "Failed to create Association."

# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

【问题讨论】:

你有一个程序 program1.py 有一些数据在 variable1 并且你想使用 qrscu.py 程序以 variable1 作为参数? 把所有东西都放在函数里面。 【参考方案1】:

将所有内容放入函数中,然后在任何你喜欢的地方调用它们:

#!/usr/bin/python
"""
For help on usage, 
python qrscu.py -h 

"""
import os
import argparse
from netdicom.applicationentity import AE
from netdicom.SOPclass import *
from dicom.dataset import Dataset, FileDataset
from dicom.UID import ExplicitVRLittleEndian, ImplicitVRLittleEndian, ExplicitVRBigEndian
import netdicom
import tempfile

# call back
def OnAssociateResponse(association):
    print "Association response received"

def OnAssociateRequest(association):
    print "Association resquested"
    return True

def OnReceiveStore(SOPClass, DS):
    print "Received C-STORE", DS.PatientName
    try:
        # do something with dataset. For instance, store it.
        file_meta = Dataset()
        file_meta.MediaStorageSOPClassUID = '1.2.840.10008.5.1.4.1.1.2'
        file_meta.MediaStorageSOPInstanceUID = "1.2.3"  # !! Need valid UID here
        file_meta.ImplementationClassUID = "1.2.3.4"  # !!! Need valid UIDs here
        filename = os.path.join(tempfile.gettempdir(), DS.SOPInstanceUID + '%s.dcm')
        ds = FileDataset(filename, , file_meta=file_meta, preamble="\0" * 128)
        ds.update(DS)
        ds.save_as(filename)
        print "File %s written" % filename
    except Exception as e:
        print "Some exception occured", e 
    # must return appropriate status
    return SOPClass.Success

def print_data(remotehost, remoteport, searchstring, local_port=9999,
        calling_title='PYNETDICOM', called_title='REMOTESCU',
        ts=(ExplicitVRLittleEndian, ImplicitVRLittleEndian, ExplicitVRBigEndian)):
    # create application entity with Find and Move SOP classes as SCU and
    # Storage SOP class as SCP
    MyAE = AE(calling_title, local_port, [PatientRootFindSOPClass,
                                PatientRootMoveSOPClass,
                                VerificationSOPClass], [StorageSOPClass], ts)
    MyAE.OnAssociateResponse = OnAssociateResponse
    MyAE.OnAssociateRequest = OnAssociateRequest
    MyAE.OnReceiveStore = OnReceiveStore
    MyAE.start()

    # remote application entity
    RemoteAE = dict(Address=remotehost, Port=remoteport, AET=called_title)

    # create association with remote AE
    print "Request association"
    assoc = MyAE.RequestAssociation(RemoteAE)

    # perform a DICOM ECHO
    print "DICOM Echo ... ",
    if not assoc:
        print "Failed to create Association."
        return

    st = assoc.VerificationSOPClass.SCU(1)
    print 'done with status "%s"' % st

    print "DICOM FindSCU ... ",
    print "\n\n----------------------------------------------------------------------\n\n"
    d = Dataset()
    d.StudyDate = searchstring
    d.QueryRetrieveLevel = "STUDY"
    d.PatientID = "*"
    study = [x[1] for x in assoc.PatientRootFindSOPClass.SCU(d, 1)][:-1]
    print 'done with status "%s"' % st
    print "\n\n\n Cont...", study
    print "\n\n----------------------------------------------------------------------\n\n"
    # loop on patients
    for pp in study:
        print "\n\n----------------------Pateint Detals------------------------------------------------\n\n"
        print "%s - %s" % (pp.StudyDate, pp.PatientID)
        # find studies
        d = Dataset()
        d.PatientID = pp.PatientID
        d.QueryRetrieveLevel = "STUDY"
        d.PatientName = ""
        d.StudyInstanceUID = ""
        d.StudyDate = ""
        d.StudyTime = ""
        d.StudyID = ""
        d.ModalitiesInStudy = ""
        d.StudyDescription = ""
        studies = [x[1] for x in assoc.PatientRootFindSOPClass.SCU(d, 1)][:-1]
        # loop on studies
        for st in studies:
            print "\n study :: ", studies
            print "\n\n---------------------------Study---------------------------\n\n"
            print "    %s - %s %s" % (st.StudyDescription, st.StudyDate, st.StudyTime)
            d = Dataset()
            d.QueryRetrieveLevel = "SERIES"
            d.StudyInstanceUID = st.StudyInstanceUID
            d.SeriesInstanceUID = ""
            d.InstanceNumber = ""
            d.Modality = ""
            d.SeriesNumber = ""
            d.SeriesDescription = ""
            d.AccessionNumber = ""
            d.SeriesDate = ""
            d.SeriesTime = ""
            d.SeriesID = ""
            d.NumberOfSeriesRelatedInstances = ""
            series = [x[1] for x in assoc.PatientRootFindSOPClass.SCU(d, 1)][:-1]

            # print series uid and number of instances
            for se in series:
                print "\n\n---------------------------Series---------------------------\n\n"
                print "\n\n\n series", se
                print " %15s - %10s - %35s - %5s" % (se.SeriesNumber, se.Modality, se.SeriesDescription, se.NumberOfSeriesRelatedInstances)

    print "Release association"
    assoc.Release(0)

    # done
    MyAE.Quit()

def parse_commandline():
    # parse commandline
    parser = argparse.ArgumentParser(description='storage SCU example')
    print "parser", parser
    parser.add_argument('remotehost')
    parser.add_argument('remoteport', type=int)
    parser.add_argument('searchstring')
    parser.add_argument('-p', help='local server port', type=int, default=9999)
    parser.add_argument('-aet', help='calling AE title', default='PYNETDICOM')
    parser.add_argument('-aec', help='called AE title', default='REMOTESCU')
    parser.add_argument('-implicit', action='store_true', help='negociate implicit transfer syntax only', default=False)
    parser.add_argument('-explicit', action='store_true', help='negociate explicit transfer syntax only', default=False)

    args = parser.parse_args()
    print "args :::: ", type(args), args

    if args.implicit:
        ts = [ImplicitVRLittleEndian]
    elif args.explicit:
        ts = [ExplicitVRLittleEndian]
    else:
        ts = [
            ExplicitVRLittleEndian, 
            ImplicitVRLittleEndian, 
            ExplicitVRBigEndian
            ]
    return args, ts

if __name__ == '__main__':
    args, ts = parse_commandline()
    print_data(args.remotehost, args.remoteport, args.searchstring, args.p, args.aet, args.aec, ts)

并像这样使用它:

import your_module
your_module.print_data(remotehost, remoteport, searchstring)

【讨论】:

【参考方案2】:

您可以通过使用 pyhton 模块 subprocess 在自己的代码中合并和使用上述脚本。它将允许您使用您根据变量或对象定义的参数运行脚本。

示例:假设您有一些变量 your_arg_1...your_arg_n 可以被 grscu.py 使用。然后你可以将这些变量传递给脚本

 import subprocess
 r = subprocess.check_call(['grscu.py', your_arg_1, your_arg_2, ..., your_arg_n])

脚本中的“args = parser.parse_args()”将抓取变量并将它们传递给 MyAE 对象。有关 argparse 的更多信息,请参阅link。

【讨论】:

以上是关于在 argparse 中从变量而不是命令行获取值的主要内容,如果未能解决你的问题,请参考以下文章

为啥使用 argparse 而不是 optparse?

使用argparse(python)创建变量键/值对

如何让 argparse 使用选项而不是前缀从文件中读取参数

使用 argparse 打印命令行参数?

如何获取argparse的帮助内容,而不是打印到控制台

Python 处理脚本的命令行参数:使用argparse