1

Is there some more convenient way to write into python files than using read/write for any file (like txt files etc).

I mean python knows what actually is the structure of python file, so if I need to write into it, maybe there is some more convenient way to do it?

If there is no such way (or it is too complicated), then what would best way to normally modify python file just using normal write (example below)?

I have lots of these files in my subdirectories called:

__config__.py

These files are used as configuration. And they have unassigned python dictionary, like this:

{
  'name': 'Hello',
  'version': '0.4.1'
}

So what I need to do, is write to all those __config__.py files new version (for example 'version': '1.0.0').

Update

To be more specific, given that there is a python file with a content like this:

# Some important comment
# Some other important comment
{
'name': 'Hello',
'version': '0.4.1'
}
# Some yet another important comment

Now running some python script, it should write into python file modifying given dictionary and after writing, output should be like this:

# Some important comment
# Some other important comment
{
'name': 'Hello',
'version': '1.0.0'
}
# Some yet another important comment

So in other words, write should only modify version key value, and everything else should be kept like it was before writing.

Andrius
  • 19,658
  • 37
  • 143
  • 243
  • since the content is a dictionary, maybe you could turn it into a json and do `json.dump()`? – scarecrow Jun 23 '16 at 07:32
  • Well you can [`literal_eval()`](https://docs.python.org/3/library/ast.html#ast.literal_eval) python literals, which your file contains. Writing back in pretty format is another thing though. Maybe [pprint](https://docs.python.org/3/library/pprint.html) could help. – Ilja Everilä Jun 23 '16 at 07:34
  • Perhaps this could be helpful? http://stackoverflow.com/questions/768634/parse-a-py-file-read-the-ast-modify-it-then-write-back-the-modified-source-c – Jaxian Jun 23 '16 at 07:34
  • If its only `dict`s like your example, you could use `json` for that, it has arguments to control indentation etc. Also, you example is missing a `,` – C14L Jun 23 '16 at 07:36
  • @C14L sorry, it was a typo. – Andrius Jun 23 '16 at 07:37
  • Is this question still too broad? So can I get an asnwer how can I narrow it down? Cause I edited the question, but it is still on hold. – Andrius Jun 23 '16 at 08:02
  • This is in my opinion *way* too broad. However, since the `__config__.py` is Python code, why wouldn't you just have *code* there that reads the version from elsewhere. – Antti Haapala -- Слава Україні Jun 23 '16 at 08:24
  • How come it is too broad? I gave specific case. If such narrow case is too broad, then I dont what is not then. Well framework uses it like that, so I don't want to manually bump version for every module I have (and there are hundreds of em). – Andrius Jun 23 '16 at 08:47
  • @AnttiHaapala and what do you mean by having version elsewhere? Whats the point of that? – Andrius Jun 23 '16 at 13:39

2 Answers2

0

I came up with solution. It is not very clean, but it works. If someone has a better answer, please write it.

content = ''
file = '__config__.py'
with open(file, 'r') as f:
    content = f.readlines()
    for i, line in enumerate(content):
        # Could use regex too here
        if "'version'" in line or '"version"' in line:
            key, val = line.split(':')
            val = val.replace("'", '').replace(',', '')
            version_digits = val.split('.')
            major_version = float(version_digits[0])
            if major_version < 1:
                # compensate for actual 'version' substring
                key_end_index = line.index('version') + 8
                content[i] = line[:key_end_index] + ": '1.0.0',\n"
with open(file, 'w') as f:
    if content:
        f.writelines(content)
xandermonkey
  • 4,054
  • 2
  • 31
  • 53
Andrius
  • 19,658
  • 37
  • 143
  • 243
  • `sed` is a *nix utility that can be used for text transformations, but more popularly known for find and replace. http://www.brunolinux.com/02-The_Terminal/Find_and%20Replace_with_Sed.html. If you just want to replace version numbers here is the command to do that `sed -e "s/'version': '0.4.1'/'version': '1.0.0'/g" test.cnf > new.cnf` – scarecrow Jun 25 '16 at 09:41
0

In order to modify the config file, you can simply do sth like this:

import fileinput

lines = fileinput.input("__config__.py", inplace=True)
nameTag="\'name\'"
versionTag="\'version\'"
name=""
newVersion="\'1.0.0\'" 
for line in lines:
    if line[0] != "'":
        print(line)
    else:
        if line.startswith(nameTag):
            print(line)
            name=line[line.index(':')+1:line.index(',')]
        if line.startswith(versionTag):
            new_line = versionTag + ": " + newVersion
            print(new_line)

Notice that the print function here actually writes to a file. for more details on how the print function do the writing for you, see here

I hope it helps.

Community
  • 1
  • 1
Soheil__K
  • 642
  • 1
  • 8
  • 17
  • 1
    `fileinput` is very dangerous to use with `inplace`, you're not using it in a context manager, thus potentially standard output is redirected to that file if an exception happens in the for loop. Additionally by `.strip()`ing lines you're also removing any indentation which will break the python code on those lines. Also, the slice is very dependent on the exact phrasing – Antti Haapala -- Слава Україні Jun 23 '16 at 14:03
  • well, I didn't actually notice stripping might break python indentation in the first place.thus, +1 for your comment ! – Soheil__K Jun 23 '16 at 17:14
  • Though, if the code contains *only* a dictionary and some comments, then there is no indentation to break. – Antti Haapala -- Слава Україні Jun 23 '16 at 17:16