In Python, what is a good, or the best way to generate some random text to prepend to a file(name) that I'm saving to a server, just to make sure it does not overwrite. Thank you!
11 Answers
You could use the UUID module for generating a random string:
import uuid
filename = str(uuid.uuid4())
This is a valid choice, given that an UUID generator is extremely unlikely to produce a duplicate identifier (a file name, in this case):
Only after generating 1 billion UUIDs every second for the next 100 years, the probability of creating just one duplicate would be about 50%. The probability of one duplicate would be about 50% if every person on earth owns 600 million UUIDs.
![](../../users/profiles/201359.webp)
- 215,818
- 33
- 288
- 367
-
19this is also very useful when you want a unique filename, but don't want it created just yet. – Prof. Falken May 14 '13 at 08:44
-
18Or use `uuid.uuid4().hex` to get an hex string without dashes (`-`). – Rockallite Nov 06 '15 at 08:25
Python has facilities to generate temporary file names, see http://docs.python.org/library/tempfile.html. For instance:
In [4]: import tempfile
Each call to tempfile.NamedTemporaryFile()
results in a different temp file, and its name can be accessed with the .name
attribute, e.g.:
In [5]: tf = tempfile.NamedTemporaryFile()
In [6]: tf.name
Out[6]: 'c:\\blabla\\locals~1\\temp\\tmptecp3i'
In [7]: tf = tempfile.NamedTemporaryFile()
In [8]: tf.name
Out[8]: 'c:\\blabla\\locals~1\\temp\\tmpr8vvme'
Once you have the unique filename it can be used like any regular file. Note: By default the file will be deleted when it is
closed. However, if the delete
parameter is False, the file is not
automatically deleted.
Full parameter set:
tempfile.NamedTemporaryFile([mode='w+b'[, bufsize=-1[, suffix=''[, prefix='tmp'[, dir=None[, delete=True]]]]]])
it is also possible to specify the prefix for the temporary file (as one of the various parameters that can be supplied during the file creation):
In [9]: tf = tempfile.NamedTemporaryFile(prefix="zz")
In [10]: tf.name
Out[10]: 'c:\\blabla\\locals~1\\temp\\zzrc3pzk'
Additional examples for working with temporary files can be found here
![](../../users/profiles/1209279.webp)
- 118,296
- 31
- 184
- 178
-
1
-
20The problem with this solution is that it generates not only a file name, but also a file that is already open. If you need a temporary file name for a new, not yet existing file (e.g., to use as output of an os command), this will not do. In that case, you can do something like str(uuid.uuid4()) . – Luca Jul 23 '16 at 18:20
-
@Luca Thanks for the additional comment, that is useful, and noted for future reference. However, OP clearly stated that he/she wanted to save a file, hence need to open it, so this solution provides for that. – Levon Jul 23 '16 at 18:27
-
It depends. Perhaps he needs the name to construct an appropriate server call. Not sure. At any rate your reply is certainly the more common case. – Luca Jul 24 '16 at 00:25
a common approach is to add a timestamp as a prefix/suffix to the filename to have some temporal relation to the file. If you need more uniqueness you can still add a random string to this.
import datetime
basename = "mylogfile"
suffix = datetime.datetime.now().strftime("%y%m%d_%H%M%S")
filename = "_".join([basename, suffix]) # e.g. 'mylogfile_120508_171442'
![](../../users/profiles/1025391.webp)
- 28,315
- 14
- 88
- 166
-
4In a multi-threaded environment, there's a possible race condition involved in the sequence `1. Test if file exists, 2. create file.` If another process interrupts yours between steps 1 and 2, and creates the file, when your code resumes it will overwrite the other process' file. – Li-aung Yip May 08 '12 at 15:36
-
@Li-aungYip In addition can also use 6-8 [random character sequence](http://stackoverflow.com/questions/2257441/python-random-string-generation-with-upper-case-letters-and-digits/2257449#2257449) (in case 2 files are generated in the same second). – bobobobo Apr 09 '13 at 17:50
-
@bobobobo: Or you could use the `tempfile` module, which handles this for you. :) – Li-aung Yip Apr 10 '13 at 02:57
-
I'd suggest to add microseconds i.e. `...strftime("%y%m%d_%H%M%S%f")` – AstraSerg Oct 31 '19 at 20:21
The OP requested to create random filenames not random files. Times and UUIDs can collide. If you are working on a single machine (not a shared filesystem) and your process/thread will not stomp on itselfk, use os.getpid() to get your own PID and use this as an element of a unique filename. Other processes would obviously not get the same PID. If you are multithreaded, get the thread id. If you have other aspects of your code in which a single thread or process could generate multiple different tempfiles, you might need to use another technique. A rolling index can work (if you aren't keeping them so long or using so many files you would worry about rollover). Keeping a global hash/index to "active" files would suffice in that case.
So sorry for the longwinded explanation, but it does depend on your exact usage.
![](../../users/profiles/221768.webp)
- 10,528
- 7
- 48
- 68
If you need no the file path, but only the random string having predefined length you can use something like this.
>>> import random
>>> import string
>>> file_name = ''.join(random.choice(string.ascii_lowercase) for i in range(16))
>>> file_name
'ytrvmyhkaxlfaugx'
![](../../users/profiles/2061081.webp)
- 3,063
- 2
- 16
- 28
If you want to preserve the original filename as a part of the new filename, unique prefixes of uniform length can be generated by using MD5 hashes of the current time:
from hashlib import md5
from time import localtime
def add_prefix(filename):
prefix = md5(str(localtime()).encode('utf-8')).hexdigest()
return f"{prefix}_{filename}"
Calls to the add_prefix('style.css') generates sequence like:
a38ff35794ae366e442a0606e67035ba_style.css
7a5f8289323b0ebfdbc7c840ad3cb67b_style.css
![](../../users/profiles/5044587.webp)
- 4,083
- 1
- 18
- 30
![](../../users/profiles/233905.webp)
- 2,454
- 16
- 17
-
1To avoid: Unicode-objects must be encoded before hashing I changed to md5(str(localtime()).encode('utf-8')).hexdigest() – PhoebeB Aug 04 '17 at 12:17
-
1Note that a hash of any kind of data (including a timestamp) does not ensure uniqueness by itself (any more than a randomly chosen byte sequence does). – Peter O. Jun 24 '20 at 20:51
Adding my two cents here:
In [19]: tempfile.mkstemp('.png', 'bingo', '/tmp')[1]
Out[19]: '/tmp/bingoy6s3_k.png'
According to the python doc for tempfile.mkstemp, it creates a temporary file in the most secure manner possible. Please note that the file will exist after this call:
In [20]: os.path.exists(tempfile.mkstemp('.png', 'bingo', '/tmp')[1])
Out[20]: True
![](../../users/profiles/2048353.webp)
- 1,311
- 1
- 12
- 24
I personally prefer to have my text to not be only random/unique but beautiful as well, that's why I like the hashids lib, which generates nice looking random text from integers. Can installed through
pip install hashids
Snippet:
import hashids
hashids = hashids.Hashids(salt="this is my salt", )
print hashids.encode(1, 2, 3)
>>> laHquq
Short Description:
Hashids is a small open-source library that generates short, unique, non-sequential ids from numbers.
![](../../users/profiles/1767754.webp)
- 18,800
- 14
- 111
- 133
>>> import random
>>> import string
>>> alias = ''.join(random.choice(string.ascii_letters) for _ in range(16))
>>> alias
'WrVkPmjeSOgTmCRG'
You could change 'string.ascii_letters' to any string format as you like to generate any other text, for example mobile NO, ID...
![](../../users/profiles/5653036.webp)
- 343
- 3
- 5
import uuid
imageName = '{}{:-%Y%m%d%H%M%S}.jpeg'.format(str(uuid.uuid4().hex), datetime.now())
![](../../users/profiles/6944841.webp)
- 88
- 7
-
1While this code may solve the question, [including an explanation](//meta.stackexchange.com/q/114762) of how and why this solves the problem would really help to improve the quality of your post, and probably result in more up-votes. Remember that you are answering the question for readers in the future, not just the person asking now. Please [edit] your answer to add explanations and give an indication of what limitations and assumptions apply. – Богдан Опир Jun 29 '20 at 12:36
You could use the random package:
import random
file = random.random()
![](../../users/profiles/2313095.webp)
- 69
- 2
-
-
-
Thank you. This answer is a good submission, but it helps to provide a more complete demo. – David Golembiowski Feb 25 '21 at 21:11