2

My goal is to create a python's script, which will format/modify the xml file. Path to file & filename are to be given as arguments in command line.

Here is my code below:

import lxml.etree as etree
from argparse import ArgumentParser
import sys
import os

def main():
    parser = ArgumentParser()
    parser.add_argument('-p', '--path', help="path to file's directory", required=True)
    parser.add_argument('-f', '--file', help="file name", required=True)
    args = parser.parse_args()

    root_dir = sys.argv[1]
    file_name = sys.argv[2]

    path = sys.argv[1] + sys.argv[2]

    for dirpath, dirnames, files in os.walk(root_dir):
        for file in files:
            if file == file_name:
                print(os.path.join(dirpath, file_name))

                with open(path, 'r', encoding="utf8") as myfile:
                    try:
                        print("DONE")
                        parser = etree.XMLParser(remove_blank_text = True)
                        tree = etree.parse(path, parser)
                        tree.write(path, pretty_print = True)

                    except IOError:
                        print("IO Exception Occured")

if __name__ == "__main__":
    main()

When I run it from cmd - I have 0 errors, but the file is not formatted, even though I give the filename that doesn't exist - still no errors. So when I run it from cmd - nothing happens.

When I try to debug it in Visual Studio, there is error that 2 arguments need to be given. Can anybody tell me how to fix my code, I have no idea where I have wrong code?

  • When I run this from command line: `error: the following arguments are required: -p/--path, -f/--file` – David Zemens Jul 10 '19 at 12:50
  • 1
    Do you run it with arguments? –  Jul 10 '19 at 12:51
  • You should get an error! How are you running it? If you run from command line you can use the [python debugger](https://docs.python.org/3/library/pdb.html) to set a breakpoint and debug it from command line. Otherwise in visual studio you can pass arguments by going to Properties--> Debug as explained [here](https://stackoverflow.com/questions/298708/debugging-with-command-line-parameters-in-visual-studio). Maybe this can help debugging it.. – freerafiki Jul 10 '19 at 12:52
  • with/without. same error. show us how you're running it. my guess is that you're mis-using ArgumentParser (I'm familiar with, but never actually use this library so I could be mistaken here) – David Zemens Jul 10 '19 at 12:53
  • ```python XmlFormat.py -p c:\User\Desktop\test\ -f test.xml``` –  Jul 10 '19 at 12:54
  • if I run this with named arguments like that, then I don't get any errors and the program appears to run successfully. You'll have to excuse me, I'm not creating xml files and formatting, I've commented out that code and only retain a few print statements to ensure the `main` procedure is running without error. – David Zemens Jul 10 '19 at 12:58
  • If you give a filename that doesn't exist, this condition (`if file == file_name:`) will *always* be false, so the inner code will not execute in that case, no error will occur based on invalid filename. – David Zemens Jul 10 '19 at 12:59
  • 1
    I think you are doing two things at the same time. First you are parsing the command line argument into the ArgumentParser (so they will be in args.file and args.path) but then you are reading sys.argv[1] and sys.argv[2] and not using args anymore. You should choose one of the two methods for reading the parameters! – freerafiki Jul 10 '19 at 13:00
  • So I should use args.file & args.path later in my program? –  Jul 10 '19 at 13:00

2 Answers2

3

You're misusing/combining/confusing sys.argv and ArgumentParser. This code actually gives you the unexpected result, because your variables are not what you think they are!

root_dir = sys.argv[1]
file_name = sys.argv[2]
# Add some print statements to examine these variables:
print(f'root_dir:{root_dir}')
print(f'file_name:{file_name}')

Look:

enter image description here

Do this instead:

    root_dir = args.path
    file_name = args.file

Here is code I used to test:

from argparse import ArgumentParser
import sys

def main():
    parser = ArgumentParser()
    parser.add_argument('-p', '--path', help="path to file's directory", required=True)
    parser.add_argument('-f', '--file', help="file name", required=True)
    args = parser.parse_args()

    root_dir = args.path
    file_name = args.file
    print(f'root_dir:{root_dir}')
    print(f'file_name:{file_name}')

if __name__ == "__main__":
    main()
David Zemens
  • 53,033
  • 11
  • 81
  • 130
  • Yes, I have done it after reading comments under the post and it works now. Thank you. –  Jul 10 '19 at 13:04
1

You are mixing two things!

METHOD 1

Launch with XmlFormat.py -p c:\User\Desktop\test\ -f test.xml

import lxml.etree as etree
from argparse import ArgumentParser
import sys
import os

def main():
    parser = ArgumentParser()
    parser.add_argument('-p', '--path', help="path to file's directory", required=True)
    parser.add_argument('-f', '--file', help="file name", required=True)
    args = parser.parse_args()

    root_dir = args.path
    file_name = args.file

    path = root_dir + file_name

    for dirpath, dirnames, files in os.walk(root_dir):
        for file in files:
            if file == file_name:
                print(os.path.join(dirpath, file_name))

                with open(path, 'r', encoding="utf8") as myfile:
                    try:
                        print("DONE")
                        parser = etree.XMLParser(remove_blank_text = True)
                        tree = etree.parse(path, parser)
                        tree.write(path, pretty_print = True)

                    except IOError:
                        print("IO Exception Occured")

if __name__ == "__main__":
    main()

METHOD 2

Launch with XmlFormat.py c:\User\Desktop\test\ test.xml (do not use -p and -f)

import lxml.etree as etree
from argparse import ArgumentParser
import sys
import os

def main():
    root_dir = sys.argv[1]
    file_name = sys.argv[2]

    path = root_dir + file_name

    for dirpath, dirnames, files in os.walk(root_dir):
        for file in files:
            if file == file_name:
                print(os.path.join(dirpath, file_name))

                with open(path, 'r', encoding="utf8") as myfile:
                    try:
                        print("DONE")
                        parser = etree.XMLParser(remove_blank_text = True)
                        tree = etree.parse(path, parser)
                        tree.write(path, pretty_print = True)

                    except IOError:
                        print("IO Exception Occured")

if __name__ == "__main__":
    main()
freerafiki
  • 539
  • 3
  • 10